diff --git a/.github/workflows/issue-label-assign.yml b/.github/workflows/issue-label-assign.yml index 181db20c10541..5c03b0138c56b 100644 --- a/.github/workflows/issue-label-assign.yml +++ b/.github/workflows/issue-label-assign.yml @@ -137,7 +137,6 @@ env: {"area":"@aws-cdk/aws-dms","keywords":["aws-dms","dms"],"labels":["@aws-cdk/aws-dms"]}, {"area":"@aws-cdk/aws-docdb","keywords":["aws-docdb","docdb"],"labels":["@aws-cdk/aws-docdb"]}, {"area":"@aws-cdk/aws-dynamodb","keywords":["aws-dynamodb","dynamo-db"],"labels":["@aws-cdk/aws-dynamodb"]}, - {"area":"@aws-cdk/aws-dynamodb-global","keywords":["aws-dynamodb-global","dynamodb-global"],"labels":["@aws-cdk/aws-dynamodb-global"]}, {"area":"@aws-cdk/aws-ec2","keywords":["aws-ec2","ec2","vpc","privatesubnet","publicsubnet","vpngateway","vpnconnection","networkacl"],"labels":["@aws-cdk/aws-ec2"]}, {"area":"@aws-cdk/aws-ecr","keywords":["aws-ecr","ecr"],"labels":["@aws-cdk/aws-ecr"]}, {"area":"@aws-cdk/aws-ecr-assets","keywords":["aws-ecr-assets","ecrassets"],"labels":["@aws-cdk/aws-ecr-assets"]}, diff --git a/.gitignore b/.gitignore index d8b560ceb8ac9..d2fe9695fc54d 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,6 @@ yarn-error.log /.versionrc.json RELEASE_NOTES.md + +# Produced by integ tests +read*lock diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index be6685a57655e..b273fa1d1a2aa 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.66.1-alpha.0](https://github.com/aws/aws-cdk/compare/v2.66.0-alpha.0...v2.66.1-alpha.0) (2023-02-23) + ## [2.66.0-alpha.0](https://github.com/aws/aws-cdk/compare/v2.65.0-alpha.0...v2.66.0-alpha.0) (2023-02-21) diff --git a/CHANGELOG.v2.md b/CHANGELOG.v2.md index a8548976c3d97..b517ec1dfa68c 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.66.1](https://github.com/aws/aws-cdk/compare/v2.66.0...v2.66.1) (2023-02-23) + + +### Bug Fixes + +* Correct SamlConsolePrincipal for non-China ([#24277](https://github.com/aws/aws-cdk/issues/24277)) ([d562871](https://github.com/aws/aws-cdk/commit/d562871824350483e80bf6a28868280381e9e83e)), closes [#24243](https://github.com/aws/aws-cdk/issues/24243) + ## [2.66.0](https://github.com/aws/aws-cdk/compare/v2.65.0...v2.66.0) (2023-02-21) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e09a8e2f4562e..22245baafecde 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,7 +60,7 @@ The following tools need to be installed on your system prior to installing the - [Node.js >= 14.15.0](https://nodejs.org/download/release/latest-v14.x/) - We recommend using a version in [Active LTS](https://nodejs.org/en/about/releases/) - [Yarn >= 1.19.1, < 2](https://yarnpkg.com/lang/en/docs/install) -- [.NET Core SDK >= 3.1.x](https://www.microsoft.com/net/download) +- [.NET SDK >= 6.0.x](https://www.microsoft.com/net/download) - [Python >= 3.6.5, < 4.0](https://www.python.org/downloads/release/python-365/) - [Docker >= 19.03](https://docs.docker.com/get-docker/) - the Docker daemon must also be running diff --git a/README.md b/README.md index 3395782708ae6..4b1cfb2405421 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The CDK is available in the following languages: - We recommend using a version in [Active LTS](https://nodejs.org/en/about/releases/) * Python ([Python ≥ 3.6](https://www.python.org/downloads/)) * Java ([Java ≥ 8](https://www.oracle.com/technetwork/java/javase/downloads/index.html) and [Maven ≥ 3.5.4](https://maven.apache.org/download.cgi)) -* .NET ([.NET Core ≥ 3.1](https://dotnet.microsoft.com/download)) +* .NET ([.NET ≥ 6.0](https://dotnet.microsoft.com/download)) * Go ([Go ≥ 1.16.4](https://golang.org/)) Third-party Language Deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice. diff --git a/package.json b/package.json index 74b8ddc59fef8..02cb1f0f0ad24 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,15 @@ "@types/node": "18.11.19", "@types/prettier": "2.6.0", "@yarnpkg/lockfile": "^1.1.0", - "cdk-generate-synthetic-examples": "^0.1.155", + "cdk-generate-synthetic-examples": "^0.1.167", "conventional-changelog-cli": "^2.2.2", "fs-extra": "^9.1.0", "graceful-fs": "^4.2.10", "jest-junit": "^13.2.0", - "jsii-diff": "1.75.0", - "jsii-pacmak": "1.75.0", - "jsii-reflect": "1.75.0", - "jsii-rosetta": "1.75.0", + "jsii-diff": "1.76.0", + "jsii-pacmak": "1.76.0", + "jsii-reflect": "1.76.0", + "jsii-rosetta": "v4.9-next", "lerna": "^4.0.0", "patch-package": "^6.5.1", "semver": "^6.3.0", diff --git a/packages/@aws-cdk-testing/cli-integ/README.md b/packages/@aws-cdk-testing/cli-integ/README.md index deafd6a5a8841..5235052342fd4 100644 --- a/packages/@aws-cdk-testing/cli-integ/README.md +++ b/packages/@aws-cdk-testing/cli-integ/README.md @@ -33,6 +33,7 @@ tests/ ├── init-python ├── init-typescript-app ├── init-typescript-lib +├── init-go └── uberpackage ``` diff --git a/packages/@aws-cdk-testing/cli-integ/bin/stage-distribution.ts b/packages/@aws-cdk-testing/cli-integ/bin/stage-distribution.ts index a5cfd6b496e5c..0c8f5e11eac53 100644 --- a/packages/@aws-cdk-testing/cli-integ/bin/stage-distribution.ts +++ b/packages/@aws-cdk-testing/cli-integ/bin/stage-distribution.ts @@ -34,6 +34,12 @@ async function main() { type: 'boolean', requiresArg: false, }) + .option('regression', { + description: 'Enable access to previous versions of the staged packages (this is expensive for CodeArtifact so we only do it when necessary)', + type: 'boolean', + requiresArg: false, + default: false, + }) .command('publish ', 'Publish a given directory', cmd => cmd .positional('DIRECTORY', { descripton: 'Directory distribution', @@ -190,6 +196,7 @@ async function publish(repo: TestRepository, usageDir: UsageDir, args: { python?: boolean; java?: boolean; dotnet?: boolean; + regression?: boolean; }) { const directory = `${args.DIRECTORY}`; const login = await repo.loginInformation(); @@ -221,8 +228,10 @@ async function publish(repo: TestRepository, usageDir: UsageDir, args: { await uploadDotnetPackages(glob.sync(path.join(directory, 'dotnet', '**', '*.nupkg')), usageDir); }); - console.log('🛍 Configuring packages for upstream versions'); - await repo.markAllUpstreamAllow(); + if (args.regression) { + console.log('🛍 Configuring packages for upstream versions'); + await repo.markAllUpstreamAllow(); + } } function whichRepos(args: { diff --git a/packages/@aws-cdk-testing/cli-integ/package.json b/packages/@aws-cdk-testing/cli-integ/package.json index 8a47dbe509cdc..c10c9e803dd9f 100644 --- a/packages/@aws-cdk-testing/cli-integ/package.json +++ b/packages/@aws-cdk-testing/cli-integ/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@octokit/rest": "^18.12.0", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "axios": "^0.27.2", "fs-extra": "^9.1.0", "glob": "^7.2.3", @@ -50,7 +50,8 @@ "p-queue": "^6.6.2", "semver": "^7.3.8", "ts-mock-imports": "^1.3.8", - "yargs": "^17.7.0" + "yaml": "1.10.2", + "yargs": "^17.7.1" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/bootstrapping.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/bootstrapping.integtest.ts index a2c56be3fe815..e5a33dae577ea 100644 --- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/bootstrapping.integtest.ts +++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/bootstrapping.integtest.ts @@ -1,5 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; +import * as yaml from 'yaml'; import { integTest, randomString, withoutBootstrap } from '../../lib'; jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime @@ -196,6 +197,41 @@ integTest('can dump the template, modify and use it to deploy a custom bootstrap }); })); +integTest('a customized template vendor will not overwrite the default template', withoutBootstrap(async (fixture) => { + // Initial bootstrap + const toolkitStackName = fixture.bootstrapStackName; + await fixture.cdkBootstrapModern({ + toolkitStackName, + cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess', + }); + + // Customize template + const templateStr = await fixture.cdkBootstrapModern({ + // toolkitStackName doesn't matter for this particular invocation + toolkitStackName, + showTemplate: true, + cliOptions: { + captureStderr: false, + }, + }); + + const template = yaml.parse(templateStr, { schema: 'core' }); + template.Parameters.BootstrapVariant.Default = 'CustomizedVendor'; + const filename = path.join(fixture.integTestDir, `${fixture.qualifier}-template.yaml`); + fs.writeFileSync(filename, yaml.stringify(template, { schema: 'yaml-1.1' }), { encoding: 'utf-8' }); + + // Rebootstrap. For some reason, this doesn't cause a failure, it's a successful no-op. + const output = await fixture.cdkBootstrapModern({ + toolkitStackName, + template: filename, + cfnExecutionPolicy: 'arn:aws:iam::aws:policy/AdministratorAccess', + cliOptions: { + captureStderr: true, + }, + }); + expect(output).toContain('Not overwriting it with a template containing'); +})); + integTest('can use the default permissions boundary to bootstrap', withoutBootstrap(async (fixture) => { let template = await fixture.cdkBootstrapModern({ // toolkitStackName doesn't matter for this particular invocation diff --git a/packages/@aws-cdk/aws-amplify/package.json b/packages/@aws-cdk/aws-amplify/package.json index 07447b969992b..f20455b24296e 100644 --- a/packages/@aws-cdk/aws-amplify/package.json +++ b/packages/@aws-cdk/aws-amplify/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jsii": "v4.9-next" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-apigateway/lib/restapi.ts b/packages/@aws-cdk/aws-apigateway/lib/restapi.ts index 7f44eddaf0ca9..41a0990e4f5f7 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/restapi.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/restapi.ts @@ -1,7 +1,7 @@ import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import { IVpcEndpoint } from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; -import { ArnFormat, CfnOutput, IResource as IResourceBase, Resource, Stack, Token, FeatureFlags, RemovalPolicy } from '@aws-cdk/core'; +import { ArnFormat, CfnOutput, IResource as IResourceBase, Resource, Stack, Token, FeatureFlags, RemovalPolicy, Size } from '@aws-cdk/core'; import { APIGATEWAY_DISABLE_CLOUDWATCH_ROLE } from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import { ApiDefinition } from './api-definition'; @@ -225,9 +225,22 @@ export interface RestApiProps extends RestApiOptions { * payload size. * * @default - Compression is disabled. + * @deprecated - superseded by `minCompressionSize` */ readonly minimumCompressionSize?: number; + /** + * A Size(in bytes, kibibytes, mebibytes etc) that is used to enable compression (with non-negative + * between 0 and 10485760 (10M) bytes, inclusive) or disable compression + * (when undefined) on an API. When compression is enabled, compression or + * decompression is not applied on the payload if the payload size is + * smaller than this value. Setting it to zero allows compression for any + * payload size. + * + * @default - Compression is disabled. + */ + readonly minCompressionSize?: Size; + /** * The ID of the API Gateway RestApi resource that you want to clone. * @@ -261,6 +274,18 @@ export interface SpecRestApiProps extends RestApiBaseProps { * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html */ readonly apiDefinition: ApiDefinition; + + /** + * A Size(in bytes, kibibytes, mebibytes etc) that is used to enable compression (with non-negative + * between 0 and 10485760 (10M) bytes, inclusive) or disable compression + * (when undefined) on an API. When compression is enabled, compression or + * decompression is not applied on the payload if the payload size is + * smaller than this value. Setting it to zero allows compression for any + * payload size. + * + * @default - Compression is disabled. + */ + readonly minCompressionSize?: Size; } /** @@ -648,6 +673,7 @@ export class SpecRestApi extends RestApiBase { name: this.restApiName, policy: props.policy, failOnWarnings: props.failOnWarnings, + minimumCompressionSize: props.minCompressionSize?.toBytes(), body: apiDefConfig.inlineDefinition ?? undefined, bodyS3Location: apiDefConfig.inlineDefinition ? undefined : apiDefConfig.s3Location, endpointConfiguration: this._configureEndpoints(props), @@ -758,12 +784,16 @@ export class RestApi extends RestApiBase { constructor(scope: Construct, id: string, props: RestApiProps = { }) { super(scope, id, props); + if (props.minCompressionSize !== undefined && props.minimumCompressionSize !== undefined) { + throw new Error('both properties minCompressionSize and minimumCompressionSize cannot be set at once.'); + } + const resource = new CfnRestApi(this, 'Resource', { name: this.physicalName, description: props.description, policy: props.policy, failOnWarnings: props.failOnWarnings, - minimumCompressionSize: props.minimumCompressionSize, + minimumCompressionSize: props.minCompressionSize?.toBytes() ?? props.minimumCompressionSize, binaryMediaTypes: props.binaryMediaTypes, endpointConfiguration: this._configureEndpoints(props), apiKeySourceType: props.apiKeySourceType, diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/apigatewayrestapiDefaultTestDeployAssert6A9696A7.assets.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/apigatewayrestapiDefaultTestDeployAssert6A9696A7.assets.json index 40422419875ec..0a13f744eed97 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/apigatewayrestapiDefaultTestDeployAssert6A9696A7.assets.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/apigatewayrestapiDefaultTestDeployAssert6A9696A7.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/cdk.out b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/cdk.out index 8ecc185e9dbee..ae4b03c54e770 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/integ.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/integ.json index ab9a770171263..67626e9b771eb 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.0.0", "testCases": { "apigateway-restapi/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/manifest.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/manifest.json index ec6db85280ab2..382751142abcf 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "30.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "test-apigateway-restapi.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/94f416193221135915e06201345d08e3db001c8bbf22b073f16ec02d3b8fba4b.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -60,7 +54,7 @@ "/test-apigateway-restapi/my-api/Deployment/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca" + "data": "myapiDeployment92F2CB496a6dee9579dae89ab3a0b094b4d193eb" } ], "/test-apigateway-restapi/my-api/DeploymentStage.beta/Resource": [ @@ -204,7 +198,7 @@ "/test-apigateway-restapi/TestDeployment/Resource": [ { "type": "aws:cdk:logicalId", - "data": "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d" + "data": "TestDeploymentD77B56860a9c34c1bc306bfbc7d318827eacd1e1" } ], "/test-apigateway-restapi/TestStage/Resource": [ @@ -231,28 +225,19 @@ "data": "CheckBootstrapVersion" } ], - "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5": [ + "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca": [ { "type": "aws:cdk:logicalId", - "data": "myapiDeployment92F2CB4963d40685c54c6f8da21d80a83f16d3d5", + "data": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca", "trace": [ "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" ] } ], - "myapiv1appliances507FEFF4": [ + "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d": [ { "type": "aws:cdk:logicalId", - "data": "myapiv1appliances507FEFF4", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" - ] - } - ], - "myapiv1appliancesGET8FE872EC": [ - { - "type": "aws:cdk:logicalId", - "data": "myapiv1appliancesGET8FE872EC", + "data": "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d", "trace": [ "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" ] @@ -307,6 +292,12 @@ ] }, "displayName": "apigateway-restapi/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.assets.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.assets.json index b397476ca59d6..09a88ca2b52e8 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.assets.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "30.0.0", "files": { - "527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049": { + "94f416193221135915e06201345d08e3db001c8bbf22b073f16ec02d3b8fba4b": { "source": { "path": "test-apigateway-restapi.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "527feb6f65d1f41404abb6acfb6504a918e1d7489665b74acb9fa0ca23f34049.json", + "objectKey": "94f416193221135915e06201345d08e3db001c8bbf22b073f16ec02d3b8fba4b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.template.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.template.json index 1e9121a7471dc..43a8699e33d49 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.template.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/test-apigateway-restapi.template.json @@ -3,6 +3,7 @@ "myapi4C7BF186": { "Type": "AWS::ApiGateway::RestApi", "Properties": { + "MinimumCompressionSize": 1024, "Name": "my-api" } }, @@ -55,7 +56,7 @@ "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" }, - "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca": { + "myapiDeployment92F2CB496a6dee9579dae89ab3a0b094b4d193eb": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -87,7 +88,7 @@ "CacheClusterEnabled": true, "CacheClusterSize": "0.5", "DeploymentId": { - "Ref": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca" + "Ref": "myapiDeployment92F2CB496a6dee9579dae89ab3a0b094b4d193eb" }, "Description": "beta stage", "MethodSettings": [ @@ -672,7 +673,7 @@ "MyHandlerServiceRoleFFA06653" ] }, - "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d": { + "TestDeploymentD77B56860a9c34c1bc306bfbc7d318827eacd1e1": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -695,7 +696,7 @@ "Ref": "myapi4C7BF186" }, "DeploymentId": { - "Ref": "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d" + "Ref": "TestDeploymentD77B56860a9c34c1bc306bfbc7d318827eacd1e1" }, "StageName": "prod" }, diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/tree.json b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/tree.json index c4920b5ecffdf..3bf0e3cc25e09 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.129" - } - }, "test-apigateway-restapi": { "id": "test-apigateway-restapi", "path": "test-apigateway-restapi", @@ -26,6 +18,7 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::ApiGateway::RestApi", "aws:cdk:cloudformation:props": { + "minimumCompressionSize": 1024, "name": "my-api" } }, @@ -38,6 +31,14 @@ "id": "CloudWatchRole", "path": "test-apigateway-restapi/my-api/CloudWatchRole", "children": { + "ImportCloudWatchRole": { + "id": "ImportCloudWatchRole", + "path": "test-apigateway-restapi/my-api/CloudWatchRole/ImportCloudWatchRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "test-apigateway-restapi/my-api/CloudWatchRole/Resource", @@ -145,7 +146,7 @@ "cacheClusterEnabled": true, "cacheClusterSize": "0.5", "deploymentId": { - "Ref": "myapiDeployment92F2CB4996088bac04ec19d9db88f146f3d88bca" + "Ref": "myapiDeployment92F2CB496a6dee9579dae89ab3a0b094b4d193eb" }, "description": "beta stage", "methodSettings": [ @@ -992,6 +993,14 @@ "id": "ServiceRole", "path": "test-apigateway-restapi/MyHandler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-apigateway-restapi/MyHandler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "test-apigateway-restapi/MyHandler/ServiceRole/Resource", @@ -1107,7 +1116,7 @@ "Ref": "myapi4C7BF186" }, "deploymentId": { - "Ref": "TestDeploymentD77B56866f3141cef1e8fea8ab3b3b8bc90df36d" + "Ref": "TestDeploymentD77B56860a9c34c1bc306bfbc7d318827eacd1e1" }, "stageName": "prod" } @@ -1156,6 +1165,22 @@ "fqn": "@aws-cdk/aws-apigateway.Stage", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-apigateway-restapi/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-apigateway-restapi/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -1176,12 +1201,30 @@ "path": "apigateway-restapi/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.129" + "version": "10.1.249" } }, "DeployAssert": { "id": "DeployAssert", "path": "apigateway-restapi/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "apigateway-restapi/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "apigateway-restapi/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -1198,6 +1241,14 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.249" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts index 4a2373e9d6aa9..47030c17160fe 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integ.restapi.ts @@ -1,5 +1,6 @@ import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; +import { Size } from '@aws-cdk/core'; import { IntegTest } from '@aws-cdk/integ-tests'; import * as apigateway from '../lib'; @@ -10,6 +11,7 @@ class Test extends cdk.Stack { const api = new apigateway.RestApi(this, 'my-api', { retainDeployments: true, cloudWatchRole: true, + minCompressionSize: Size.bytes(1024), deployOptions: { cacheClusterEnabled: true, stageName: 'beta', diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/apigatewayspecrestapiDefaultTestDeployAssertD16AA485.assets.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/apigatewayspecrestapiDefaultTestDeployAssertD16AA485.assets.json index 7c4a2beda03b5..eae4994100f87 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/apigatewayspecrestapiDefaultTestDeployAssertD16AA485.assets.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/apigatewayspecrestapiDefaultTestDeployAssertD16AA485.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/cdk.out b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/cdk.out index 8ecc185e9dbee..ae4b03c54e770 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/integ.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/integ.json index f4c240596beb4..27ab5a7e80179 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.0.0", "testCases": { "apigateway-spec-restapi/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/manifest.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/manifest.json index ec86acb97e7a9..1112099915ed4 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "30.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "test-apigateway-spec-restapi.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/4b4324bd66c0a5352124c718d0cb3990046afe7ccf1cea94d4488ed7cd67191b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a361f357c68964992ee5038aa363d75be98e145d828b8955269361c54d7722ae.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -156,7 +150,7 @@ "/test-apigateway-spec-restapi/my-api/Deployment/Resource": [ { "type": "aws:cdk:logicalId", - "data": "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1" + "data": "myapiDeployment92F2CB492c49d8fa05ada8b5cddee1ce76138bd0" } ], "/test-apigateway-spec-restapi/my-api/DeploymentStage.beta/Resource": [ @@ -212,6 +206,15 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1": [ + { + "type": "aws:cdk:logicalId", + "data": "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "test-apigateway-spec-restapi" @@ -262,6 +265,12 @@ ] }, "displayName": "apigateway-spec-restapi/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.assets.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.assets.json index 2bff91cb920f7..54d375c1f6975 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.assets.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.0.0", "files": { "68497ac876de4e963fc8f7b5f1b28844c18ecc95e3f7c6e9e0bf250e03c037fb": { "source": { @@ -14,7 +14,7 @@ } } }, - "4b4324bd66c0a5352124c718d0cb3990046afe7ccf1cea94d4488ed7cd67191b": { + "a361f357c68964992ee5038aa363d75be98e145d828b8955269361c54d7722ae": { "source": { "path": "test-apigateway-spec-restapi.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4b4324bd66c0a5352124c718d0cb3990046afe7ccf1cea94d4488ed7cd67191b.json", + "objectKey": "a361f357c68964992ee5038aa363d75be98e145d828b8955269361c54d7722ae.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.template.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.template.json index 5214b610b9995..219437fc11d7c 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.template.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/test-apigateway-spec-restapi.template.json @@ -10,6 +10,7 @@ "Key": "68497ac876de4e963fc8f7b5f1b28844c18ecc95e3f7c6e9e0bf250e03c037fb.yaml" }, "DisableExecuteApiEndpoint": true, + "MinimumCompressionSize": 1024, "Name": "my-api" } }, @@ -516,7 +517,7 @@ "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain" }, - "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1": { + "myapiDeployment92F2CB492c49d8fa05ada8b5cddee1ce76138bd0": { "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { @@ -548,7 +549,7 @@ "CacheClusterEnabled": true, "CacheClusterSize": "0.5", "DeploymentId": { - "Ref": "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1" + "Ref": "myapiDeployment92F2CB492c49d8fa05ada8b5cddee1ce76138bd0" }, "Description": "beta stage", "MethodSettings": [ diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/tree.json b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/tree.json index 10cba98b03d1a..2dd509aaa2020 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.140" - } - }, "test-apigateway-spec-restapi": { "id": "test-apigateway-spec-restapi", "path": "test-apigateway-spec-restapi", @@ -59,6 +51,7 @@ "key": "68497ac876de4e963fc8f7b5f1b28844c18ecc95e3f7c6e9e0bf250e03c037fb.yaml" }, "disableExecuteApiEndpoint": true, + "minimumCompressionSize": 1024, "name": "my-api" } }, @@ -763,6 +756,14 @@ "id": "CloudWatchRole", "path": "test-apigateway-spec-restapi/my-api/CloudWatchRole", "children": { + "ImportCloudWatchRole": { + "id": "ImportCloudWatchRole", + "path": "test-apigateway-spec-restapi/my-api/CloudWatchRole/ImportCloudWatchRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "test-apigateway-spec-restapi/my-api/CloudWatchRole/Resource", @@ -870,7 +871,7 @@ "cacheClusterEnabled": true, "cacheClusterSize": "0.5", "deploymentId": { - "Ref": "myapiDeployment92F2CB49e2ce3595b92ff44fad021c2e55149db1" + "Ref": "myapiDeployment92F2CB492c49d8fa05ada8b5cddee1ce76138bd0" }, "description": "beta stage", "methodSettings": [ @@ -1025,6 +1026,14 @@ "id": "ServiceRole", "path": "test-apigateway-spec-restapi/MyHandler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "test-apigateway-spec-restapi/MyHandler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "test-apigateway-spec-restapi/MyHandler/ServiceRole/Resource", @@ -1099,6 +1108,22 @@ "fqn": "@aws-cdk/aws-lambda.Function", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-apigateway-spec-restapi/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-apigateway-spec-restapi/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -1119,12 +1144,30 @@ "path": "apigateway-spec-restapi/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.249" } }, "DeployAssert": { "id": "DeployAssert", "path": "apigateway-spec-restapi/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "apigateway-spec-restapi/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "apigateway-spec-restapi/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -1141,6 +1184,14 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.249" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.ts b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.ts index 512fc8dd8e91c..f10f166232a2d 100644 --- a/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.ts +++ b/packages/@aws-cdk/aws-apigateway/test/integ.spec-restapi.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import * as lambda from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; +import { Size } from '@aws-cdk/core'; import { IntegTest } from '@aws-cdk/integ-tests'; import * as apigateway from '../lib'; @@ -11,6 +12,7 @@ class Test extends cdk.Stack { const api = new apigateway.SpecRestApi(this, 'my-api', { apiDefinition: apigateway.ApiDefinition.fromAsset(path.join(__dirname, 'sample-definition.yaml')), disableExecuteApiEndpoint: true, + minCompressionSize: Size.bytes(1024), retainDeployments: true, cloudWatchRole: true, deployOptions: { diff --git a/packages/@aws-cdk/aws-apigateway/test/restapi.test.ts b/packages/@aws-cdk/aws-apigateway/test/restapi.test.ts index 0156bd2cb4821..205686f7a0c5b 100644 --- a/packages/@aws-cdk/aws-apigateway/test/restapi.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/restapi.test.ts @@ -1,7 +1,7 @@ import { Template } from '@aws-cdk/assertions'; import { GatewayVpcEndpoint } from '@aws-cdk/aws-ec2'; import { testDeprecated } from '@aws-cdk/cdk-build-tools'; -import { App, CfnElement, CfnResource, Lazy, Stack } from '@aws-cdk/core'; +import { App, CfnElement, CfnResource, Lazy, Size, Stack } from '@aws-cdk/core'; import * as apigw from '../lib'; describe('restapi', () => { @@ -868,163 +868,252 @@ describe('restapi', () => { expect(method.api).toBeDefined(); }); - describe('Import', () => { - test('fromRestApiId()', () => { - // GIVEN - const stack = new Stack(); + test('RestApi minCompressionSize', () => { + // GIVEN + const app = new App({ + context: { + '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + }, + }); - // WHEN - const imported = apigw.RestApi.fromRestApiId(stack, 'imported-api', 'api-rxt4498f'); + const stack = new Stack(app); + const api = new apigw.RestApi(stack, 'RestApi', { + minCompressionSize: Size.bytes(1024), + }); - // THEN - expect(stack.resolve(imported.restApiId)).toEqual('api-rxt4498f'); - expect(imported.restApiName).toEqual('imported-api'); + // WHEN + api.root.addMethod('GET'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', { + Name: 'RestApi', + MinimumCompressionSize: 1024, }); + }); - test('fromRestApiAttributes()', () => { - // GIVEN - const stack = new Stack(); + testDeprecated('RestApi minimumCompressionSize', () => { + // GIVEN + const app = new App({ + context: { + '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + }, + }); - // WHEN - const imported = apigw.RestApi.fromRestApiAttributes(stack, 'imported-api', { - restApiId: 'test-restapi-id', - rootResourceId: 'test-root-resource-id', - }); - const resource = imported.root.addResource('pets'); - resource.addMethod('GET'); + const stack = new Stack(app); + const api = new apigw.RestApi(stack, 'RestApi', { + minimumCompressionSize: 1024, + }); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { - PathPart: 'pets', - ParentId: stack.resolve(imported.restApiRootResourceId), - }); - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { - HttpMethod: 'GET', - ResourceId: stack.resolve(resource.resourceId), - }); - expect(imported.restApiName).toEqual('imported-api'); - }); - - test('fromRestApiAttributes() with restApiName', () => { - // GIVEN - const stack = new Stack(); + // WHEN + api.root.addMethod('GET'); - // WHEN - const imported = apigw.RestApi.fromRestApiAttributes(stack, 'imported-api', { - restApiId: 'test-restapi-id', - rootResourceId: 'test-root-resource-id', - restApiName: 'test-restapi-name', - }); - const resource = imported.root.addResource('pets'); - resource.addMethod('GET'); + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', { + Name: 'RestApi', + MinimumCompressionSize: 1024, + }); + }); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { - PathPart: 'pets', - ParentId: stack.resolve(imported.restApiRootResourceId), - }); - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { - HttpMethod: 'GET', - ResourceId: stack.resolve(resource.resourceId), - }); - expect(imported.restApiName).toEqual('test-restapi-name'); + testDeprecated('throws error when both minimumCompressionSize and minCompressionSize are used', () => { + // GIVEN + const app = new App({ + context: { + '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + }, }); + + // WHEN + const stack = new Stack(app); + + // THEN + expect(() => new apigw.RestApi(stack, 'RestApi', { + minCompressionSize: Size.bytes(500), + minimumCompressionSize: 1024, + })).toThrow(/both properties minCompressionSize and minimumCompressionSize cannot be set at once./); }); +}); - describe('SpecRestApi', () => { - test('add Methods and Resources', () => { - // GIVEN - const stack = new Stack(); - const api = new apigw.SpecRestApi(stack, 'SpecRestApi', { - apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), - }); - // WHEN - const resource = api.root.addResource('pets'); - resource.addMethod('GET'); +describe('Import', () => { + test('fromRestApiId()', () => { + // GIVEN + const stack = new Stack(); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { - PathPart: 'pets', - ParentId: stack.resolve(api.restApiRootResourceId), - }); - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { - HttpMethod: 'GET', - ResourceId: stack.resolve(resource.resourceId), - }); + // WHEN + const imported = apigw.RestApi.fromRestApiId(stack, 'imported-api', 'api-rxt4498f'); + + // THEN + expect(stack.resolve(imported.restApiId)).toEqual('api-rxt4498f'); + expect(imported.restApiName).toEqual('imported-api'); + }); + + test('fromRestApiAttributes()', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const imported = apigw.RestApi.fromRestApiAttributes(stack, 'imported-api', { + restApiId: 'test-restapi-id', + rootResourceId: 'test-root-resource-id', }); + const resource = imported.root.addResource('pets'); + resource.addMethod('GET'); - test('"endpointTypes" can be used to specify endpoint configuration for SpecRestApi', () => { - // GIVEN - const stack = new Stack(); + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { + PathPart: 'pets', + ParentId: stack.resolve(imported.restApiRootResourceId), + }); + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { + HttpMethod: 'GET', + ResourceId: stack.resolve(resource.resourceId), + }); + expect(imported.restApiName).toEqual('imported-api'); + }); - // WHEN - const api = new apigw.SpecRestApi(stack, 'api', { - apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), - endpointTypes: [apigw.EndpointType.EDGE, apigw.EndpointType.PRIVATE], - }); + test('fromRestApiAttributes() with restApiName', () => { + // GIVEN + const stack = new Stack(); - api.root.addMethod('GET'); + // WHEN + const imported = apigw.RestApi.fromRestApiAttributes(stack, 'imported-api', { + restApiId: 'test-restapi-id', + rootResourceId: 'test-root-resource-id', + restApiName: 'test-restapi-name', + }); + const resource = imported.root.addResource('pets'); + resource.addMethod('GET'); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', { - EndpointConfiguration: { - Types: [ - 'EDGE', - 'PRIVATE', - ], - }, - }); + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { + PathPart: 'pets', + ParentId: stack.resolve(imported.restApiRootResourceId), }); + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { + HttpMethod: 'GET', + ResourceId: stack.resolve(resource.resourceId), + }); + expect(imported.restApiName).toEqual('test-restapi-name'); + }); +}); - testDeprecated('addApiKey is supported', () => { - // GIVEN - const stack = new Stack(); - const api = new apigw.SpecRestApi(stack, 'myapi', { - apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), - }); - api.root.addMethod('OPTIONS'); +describe('SpecRestApi', () => { + test('add Methods and Resources', () => { + // GIVEN + const stack = new Stack(); + const api = new apigw.SpecRestApi(stack, 'SpecRestApi', { + apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), + }); - // WHEN - api.addApiKey('myapikey', { - apiKeyName: 'myApiKey1', - value: '01234567890ABCDEFabcdef', - }); + // WHEN + const resource = api.root.addResource('pets'); + resource.addMethod('GET'); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::ApiKey', { - Enabled: true, - Name: 'myApiKey1', - StageKeys: [ - { - RestApiId: { Ref: 'myapi162F20B8' }, - StageName: { Ref: 'myapiDeploymentStageprod329F21FF' }, - }, + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Resource', { + PathPart: 'pets', + ParentId: stack.resolve(api.restApiRootResourceId), + }); + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::Method', { + HttpMethod: 'GET', + ResourceId: stack.resolve(resource.resourceId), + }); + }); + + test('"endpointTypes" can be used to specify endpoint configuration for SpecRestApi', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const api = new apigw.SpecRestApi(stack, 'api', { + apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), + endpointTypes: [apigw.EndpointType.EDGE, apigw.EndpointType.PRIVATE], + }); + + api.root.addMethod('GET'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', { + EndpointConfiguration: { + Types: [ + 'EDGE', + 'PRIVATE', ], - Value: '01234567890ABCDEFabcdef', - }); + }, }); + }); - test('featureFlag @aws-cdk/aws-apigateway:disableCloudWatchRole CloudWatch role is not created created for API Gateway', () => { - // GIVEN - const app = new App({ - context: { - '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + testDeprecated('addApiKey is supported', () => { + // GIVEN + const stack = new Stack(); + const api = new apigw.SpecRestApi(stack, 'myapi', { + apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), + }); + api.root.addMethod('OPTIONS'); + + // WHEN + api.addApiKey('myapikey', { + apiKeyName: 'myApiKey1', + value: '01234567890ABCDEFabcdef', + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::ApiKey', { + Enabled: true, + Name: 'myApiKey1', + StageKeys: [ + { + RestApiId: { Ref: 'myapi162F20B8' }, + StageName: { Ref: 'myapiDeploymentStageprod329F21FF' }, }, - }); + ], + Value: '01234567890ABCDEFabcdef', + }); + }); - const stack = new Stack(app); - const api = new apigw.SpecRestApi(stack, 'SpecRestApi', { - apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), - }); + test('featureFlag @aws-cdk/aws-apigateway:disableCloudWatchRole CloudWatch role is not created created for API Gateway', () => { + // GIVEN + const app = new App({ + context: { + '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + }, + }); - // WHEN - const resource = api.root.addResource('pets'); - resource.addMethod('GET'); + const stack = new Stack(app); + const api = new apigw.SpecRestApi(stack, 'SpecRestApi', { + apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), + }); - // THEN - Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 0); - Template.fromStack(stack).resourceCountIs('AWS::ApiGateway::Account', 0); + // WHEN + const resource = api.root.addResource('pets'); + resource.addMethod('GET'); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 0); + Template.fromStack(stack).resourceCountIs('AWS::ApiGateway::Account', 0); + }); + + test('SpecRestApi minimumCompressionSize', () => { + // GIVEN + const app = new App({ + context: { + '@aws-cdk/aws-apigateway:disableCloudWatchRole': true, + }, + }); + + const stack = new Stack(app); + const api = new apigw.SpecRestApi(stack, 'SpecRestApi', { + apiDefinition: apigw.ApiDefinition.fromInline({ foo: 'bar' }), + minCompressionSize: Size.bytes(1024), + }); + + // WHEN + api.root.addMethod('GET'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGateway::RestApi', { + Name: 'SpecRestApi', + MinimumCompressionSize: 1024, }); }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json index 84874ef955ba9..8e19141b46930 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json +++ b/packages/@aws-cdk/aws-apigatewayv2-authorizers/package.json @@ -85,7 +85,7 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@aws-cdk/integ-tests": "0.0.0", "@types/jest": "^27.5.2", "jsii": "v4.9-next" diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.assets.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.assets.json index 6f9a7efb4533c..610a2c40c6d1c 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.assets.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.assets.json @@ -1,7 +1,7 @@ { "version": "22.0.0", "files": { - "768b8ff8b1178a04dbfca488da9459f4f402bfad643db0b4791787ef23ec4db5": { + "2f0699c7863c01ee4fb7ccca4b192b311d9d6723f012b40f36bdf25a5db22f0c": { "source": { "path": "aws-cdk-asg-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "768b8ff8b1178a04dbfca488da9459f4f402bfad643db0b4791787ef23ec4db5.json", + "objectKey": "2f0699c7863c01ee4fb7ccca4b192b311d9d6723f012b40f36bdf25a5db22f0c.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.template.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.template.json index 0698ba8c6c24d..69bff2fd6e318 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.template.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/aws-cdk-asg-integ.template.json @@ -27,7 +27,10 @@ } ] } - ] + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } }, "TagSpecifications": [ { @@ -69,7 +72,10 @@ } ] } - ] + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } }, "TagSpecifications": [ { diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/manifest.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/manifest.json index 2aaf97a525a2a..7e4747019548a 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/manifest.json @@ -17,7 +17,7 @@ "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}/768b8ff8b1178a04dbfca488da9459f4f402bfad643db0b4791787ef23ec4db5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2f0699c7863c01ee4fb7ccca4b192b311d9d6723f012b40f36bdf25a5db22f0c.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/tree.json b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/tree.json index a5f63ed131aae..e6c641f4d3a8c 100644 --- a/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-autoscaling/test/integ.asg-lt.js.snapshot/tree.json @@ -42,7 +42,10 @@ } ] } - ] + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } }, "tagSpecifications": [ { @@ -118,7 +121,10 @@ } ] } - ] + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } }, "tagSpecifications": [ { @@ -1275,7 +1281,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.189" } } }, diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/BatchWithEFSTestDefaultTestDeployAssert0F887B55.assets.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/BatchWithEFSTestDefaultTestDeployAssert0F887B55.assets.json index 6f2911b10864e..3a915fbe9e315 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/BatchWithEFSTestDefaultTestDeployAssert0F887B55.assets.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/BatchWithEFSTestDefaultTestDeployAssert0F887B55.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.assets.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.assets.json index f5ced56610124..4f1e56ca8afe6 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.assets.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { - "742f32336d22265973f0e225f7f35f8254d591f606eb0b3fbbc4ffbe4909a323": { + "dea8441064e2b7f93a29d086bcfc92bbdd9b163aed56cc08208f3ec941e96441": { "source": { "path": "batch-stack.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "742f32336d22265973f0e225f7f35f8254d591f606eb0b3fbbc4ffbe4909a323.json", + "objectKey": "dea8441064e2b7f93a29d086bcfc92bbdd9b163aed56cc08208f3ec941e96441.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.template.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.template.json index 76d049affafdb..e7cf6f760094e 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.template.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/batch-stack.template.json @@ -577,6 +577,12 @@ "FileSystemId": { "Ref": "EFSF3301CFD" }, + "AccessPointTags": [ + { + "Key": "Name", + "Value": "batch-stack/EFSAccessPoint" + } + ], "PosixUser": { "Gid": "1000", "Uid": "1000" diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/cdk.out b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/integ.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/integ.json index d96168e1c2dd6..c48cd863fc5e6 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "BatchWithEFSTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/manifest.json index 0f03538f69fa3..57c6b4202d2fe 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "batch-stack.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/742f32336d22265973f0e225f7f35f8254d591f606eb0b3fbbc4ffbe4909a323.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/dea8441064e2b7f93a29d086bcfc92bbdd9b163aed56cc08208f3ec941e96441.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -490,6 +484,12 @@ ] }, "displayName": "BatchWithEFSTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/tree.json b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/tree.json index a6ba9cf4b5ca2..bece4c4bbb608 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch-with-efs.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.140" - } - }, "batch-stack": { "id": "batch-stack", "path": "batch-stack", @@ -942,6 +934,12 @@ "fileSystemId": { "Ref": "EFSF3301CFD" }, + "accessPointTags": [ + { + "key": "Name", + "value": "batch-stack/EFSAccessPoint" + } + ], "posixUser": { "uid": "1000", "gid": "1000" @@ -970,6 +968,14 @@ "id": "DefaultJobRole", "path": "batch-stack/DefaultJobRole", "children": { + "ImportDefaultJobRole": { + "id": "ImportDefaultJobRole", + "path": "batch-stack/DefaultJobRole/ImportDefaultJobRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/DefaultJobRole/Resource", @@ -1132,6 +1138,14 @@ "id": "Ecs-Instance-Role", "path": "batch-stack/batch-demand-compute-env-launch-template/Ecs-Instance-Role", "children": { + "ImportEcs-Instance-Role": { + "id": "ImportEcs-Instance-Role", + "path": "batch-stack/batch-demand-compute-env-launch-template/Ecs-Instance-Role/ImportEcs-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-demand-compute-env-launch-template/Ecs-Instance-Role/Resource", @@ -1199,6 +1213,14 @@ "id": "Resource-Service-Instance-Role", "path": "batch-stack/batch-demand-compute-env-launch-template/Resource-Service-Instance-Role", "children": { + "ImportResource-Service-Instance-Role": { + "id": "ImportResource-Service-Instance-Role", + "path": "batch-stack/batch-demand-compute-env-launch-template/Resource-Service-Instance-Role/ImportResource-Service-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-demand-compute-env-launch-template/Resource-Service-Instance-Role/Resource", @@ -1358,6 +1380,14 @@ "id": "Ecs-Instance-Role", "path": "batch-stack/batch-spot-compute-env/Ecs-Instance-Role", "children": { + "ImportEcs-Instance-Role": { + "id": "ImportEcs-Instance-Role", + "path": "batch-stack/batch-spot-compute-env/Ecs-Instance-Role/ImportEcs-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-spot-compute-env/Ecs-Instance-Role/Resource", @@ -1425,6 +1455,14 @@ "id": "Resource-Service-Instance-Role", "path": "batch-stack/batch-spot-compute-env/Resource-Service-Instance-Role", "children": { + "ImportResource-Service-Instance-Role": { + "id": "ImportResource-Service-Instance-Role", + "path": "batch-stack/batch-spot-compute-env/Resource-Service-Instance-Role/ImportResource-Service-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-spot-compute-env/Resource-Service-Instance-Role/Resource", @@ -1587,6 +1625,14 @@ "id": "Ecs-Instance-Role", "path": "batch-stack/batch-demand-compute-env-launch-template-2/Ecs-Instance-Role", "children": { + "ImportEcs-Instance-Role": { + "id": "ImportEcs-Instance-Role", + "path": "batch-stack/batch-demand-compute-env-launch-template-2/Ecs-Instance-Role/ImportEcs-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-demand-compute-env-launch-template-2/Ecs-Instance-Role/Resource", @@ -1654,6 +1700,14 @@ "id": "Resource-Service-Instance-Role", "path": "batch-stack/batch-demand-compute-env-launch-template-2/Resource-Service-Instance-Role", "children": { + "ImportResource-Service-Instance-Role": { + "id": "ImportResource-Service-Instance-Role", + "path": "batch-stack/batch-demand-compute-env-launch-template-2/Resource-Service-Instance-Role/ImportResource-Service-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-demand-compute-env-launch-template-2/Resource-Service-Instance-Role/Resource", @@ -1852,6 +1906,14 @@ "id": "Resource-Service-Instance-Role", "path": "batch-stack/batch-fargate-compute-env/Resource-Service-Instance-Role", "children": { + "ImportResource-Service-Instance-Role": { + "id": "ImportResource-Service-Instance-Role", + "path": "batch-stack/batch-fargate-compute-env/Resource-Service-Instance-Role/ImportResource-Service-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-fargate-compute-env/Resource-Service-Instance-Role/Resource", @@ -1986,6 +2048,14 @@ "id": "Resource-Service-Instance-Role", "path": "batch-stack/batch-fargate-spot-compute-env/Resource-Service-Instance-Role", "children": { + "ImportResource-Service-Instance-Role": { + "id": "ImportResource-Service-Instance-Role", + "path": "batch-stack/batch-fargate-spot-compute-env/Resource-Service-Instance-Role/ImportResource-Service-Instance-Role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/batch-fargate-spot-compute-env/Resource-Service-Instance-Role/Resource", @@ -2313,6 +2383,14 @@ "id": "execution-role", "path": "batch-stack/execution-role", "children": { + "Importexecution-role": { + "id": "Importexecution-role", + "path": "batch-stack/execution-role/Importexecution-role", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "batch-stack/execution-role/Resource", @@ -2502,6 +2580,22 @@ "fqn": "@aws-cdk/aws-batch.JobDefinition", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "batch-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "batch-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -2522,12 +2616,30 @@ "path": "BatchWithEFSTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } }, "DeployAssert": { "id": "DeployAssert", "path": "BatchWithEFSTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "BatchWithEFSTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "BatchWithEFSTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -2544,6 +2656,14 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json index 3f9651aebba3d..c3b0d3fada58a 100644 --- a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json +++ b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json @@ -29,10 +29,10 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/sinon": "^9.0.11", "@aws-cdk/cdk-build-tools": "0.0.0", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "eslint": "^7.32.0", "eslint-config-standard": "^14.1.1", diff --git a/packages/@aws-cdk/aws-cloudformation/package.json b/packages/@aws-cdk/aws-cloudformation/package.json index b65281cad3c3d..3955563cb8786 100644 --- a/packages/@aws-cdk/aws-cloudformation/package.json +++ b/packages/@aws-cdk/aws-cloudformation/package.json @@ -89,7 +89,7 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-cloudfront-origins/package.json b/packages/@aws-cdk/aws-cloudfront-origins/package.json index 422c0368fa76e..932b2d8481ecf 100644 --- a/packages/@aws-cdk/aws-cloudfront-origins/package.json +++ b/packages/@aws-cdk/aws-cloudfront-origins/package.json @@ -85,7 +85,7 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0" + "aws-sdk": "^2.1325.0" }, "dependencies": { "@aws-cdk/aws-apigateway": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudfront/package.json b/packages/@aws-cdk/aws-cloudfront/package.json index f85a2538c1bd4..c01da3b4a87dc 100644 --- a/packages/@aws-cdk/aws-cloudfront/package.json +++ b/packages/@aws-cdk/aws-cloudfront/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cloudtrail/package.json b/packages/@aws-cdk/aws-cloudtrail/package.json index 1e392e3526eea..648268d27890b 100644 --- a/packages/@aws-cdk/aws-cloudtrail/package.json +++ b/packages/@aws-cdk/aws-cloudtrail/package.json @@ -87,7 +87,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts index 5068187f9b9ae..770c3604c3c5a 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/metric.ts @@ -609,9 +609,9 @@ export class MathExpression implements IMetric { // we can add warnings. const missingIdentifiers = allIdentifiersInExpression(this.expression).filter(i => !this.usingMetrics[i]); - const warnings = []; + const warnings: string[] = []; - if (!this.expression.toUpperCase().match('\\s*SELECT\\s.*') && missingIdentifiers.length > 0) { + if (!this.expression.toUpperCase().match('\\s*SELECT|SEARCH|METRICS\\s.*') && missingIdentifiers.length > 0) { warnings.push(`Math expression '${this.expression}' references unknown identifiers: ${missingIdentifiers.join(', ')}. Please add them to the 'usingMetrics' map.`); } diff --git a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts index 72e61cbd0a19a..24ffebfcfb76f 100644 --- a/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts +++ b/packages/@aws-cdk/aws-cloudwatch/test/metric-math.test.ts @@ -75,6 +75,24 @@ describe('Metric Math', () => { expect(m.warnings).toContainEqual(expect.stringContaining("'m1 + m2' references unknown identifiers")); }); + test('metrics METRICS expression does not produce warning for unknown identifier', () => { + const m = new MathExpression({ + expression: 'SUM(METRICS())', + usingMetrics: {}, + }); + + expect(m.warnings).toBeUndefined(); + }); + + test('metrics search expression does not produce warning for unknown identifier', () => { + const m = new MathExpression({ + expression: "SEARCH('{dimension_one, dimension_two} my_metric', 'Average', 300)", + usingMetrics: {}, + }); + + expect(m.warnings).toBeUndefined(); + }); + test('metrics insights expression does not produce warning for unknown identifier', () => { const m = new MathExpression({ expression: "SELECT AVG(CpuUsage) FROM EC2 WHERE Instance = '123456'", diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 86568eaeaa0ae..85b89e6d33502 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -93,7 +93,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index c9a902db27c96..90821ac3cedf1 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -93,7 +93,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.assets.json b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.assets.json index db774132f479a..e79687b2c71f4 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.assets.json +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { - "16960a7525b0e7f3fc99af30374461429f32d815db45bab3e136c4a994140575": { + "ffa0280c20139b5a0ec753fdb4365af29fb08ea9703b9139810054417bc99c10": { "source": { "path": "aws-cdk-docdb-cluster-rotation.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "16960a7525b0e7f3fc99af30374461429f32d815db45bab3e136c4a994140575.json", + "objectKey": "ffa0280c20139b5a0ec753fdb4365af29fb08ea9703b9139810054417bc99c10.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.template.json b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.template.json index 18907654c9a2e..0f59b9f2136f3 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.template.json +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-docdb-cluster-rotation.template.json @@ -508,7 +508,7 @@ } } }, - "DatabaseSecretAttachmentPolicy5ACFE6CA": { + "DatabaseSecretPolicyEE73D3F8": { "Type": "AWS::SecretsManager::ResourcePolicy", "Properties": { "ResourcePolicy": { @@ -540,7 +540,7 @@ "Version": "2012-10-17" }, "SecretId": { - "Ref": "DatabaseSecretAttachmentE5D1B020" + "Ref": "DatabaseSecret3B817195" } } }, diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/cdk.out b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/integ.json b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/integ.json index 5466489d4db95..60a46976636ef 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ.cluster-rotation.lit": { "stacks": [ diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/manifest.json b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/manifest.json index 521408f82eb4a..be159955f9791 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-docdb-cluster-rotation.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/16960a7525b0e7f3fc99af30374461429f32d815db45bab3e136c4a994140575.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/ffa0280c20139b5a0ec753fdb4365af29fb08ea9703b9139810054417bc99c10.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -213,10 +207,10 @@ "data": "DatabaseSecretAttachmentRotationScheduleA4E9F034" } ], - "/aws-cdk-docdb-cluster-rotation/Database/Secret/Attachment/Policy/Resource": [ + "/aws-cdk-docdb-cluster-rotation/Database/Secret/Policy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseSecretAttachmentPolicy5ACFE6CA" + "data": "DatabaseSecretPolicyEE73D3F8" } ], "/aws-cdk-docdb-cluster-rotation/Database/Resource": [ @@ -260,9 +254,24 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "DatabaseSecretAttachmentPolicy5ACFE6CA": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseSecretAttachmentPolicy5ACFE6CA", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "aws-cdk-docdb-cluster-rotation" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/tree.json b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/tree.json index d6b2cf350eea3..22d76ec24c566 100644 --- a/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-docdb/test/integ.cluster-rotation.lit.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-docdb-cluster-rotation": { "id": "aws-cdk-docdb-cluster-rotation", "path": "aws-cdk-docdb-cluster-rotation", @@ -91,8 +83,8 @@ "id": "Acl", "path": "aws-cdk-docdb-cluster-rotation/VPC/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -258,8 +250,8 @@ "id": "Acl", "path": "aws-cdk-docdb-cluster-rotation/VPC/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -425,8 +417,8 @@ "id": "Acl", "path": "aws-cdk-docdb-cluster-rotation/VPC/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -544,8 +536,8 @@ "id": "Acl", "path": "aws-cdk-docdb-cluster-rotation/VPC/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -850,64 +842,64 @@ "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", "version": "0.0.0" } - }, - "Policy": { - "id": "Policy", - "path": "aws-cdk-docdb-cluster-rotation/Database/Secret/Attachment/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-docdb-cluster-rotation/Database/Secret/Attachment/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", - "aws:cdk:cloudformation:props": { - "resourcePolicy": { - "Statement": [ - { - "Action": "secretsmanager:DeleteSecret", - "Effect": "Deny", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-docdb-cluster-rotation/Database/Secret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-docdb-cluster-rotation/Database/Secret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] } - ], - "Version": "2012-10-17" - }, - "secretId": { - "Ref": "DatabaseSecretAttachmentE5D1B020" + }, + "Resource": "*" } - } + ], + "Version": "2012-10-17" }, - "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "secretId": { + "Ref": "DatabaseSecret3B817195" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", "version": "0.0.0" } } @@ -1025,8 +1017,8 @@ "id": "SARMapping", "path": "aws-cdk-docdb-cluster-rotation/Database/RotationSingleUser/SARMapping", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnMapping", + "version": "0.0.0" } }, "Resource": { @@ -1120,17 +1112,41 @@ "fqn": "@aws-cdk/aws-docdb.DatabaseCluster", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-docdb-cluster-rotation/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-docdb-cluster-rotation/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/.eslintrc.js b/packages/@aws-cdk/aws-dynamodb-global/.eslintrc.js deleted file mode 100644 index 2658ee8727166..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -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-dynamodb-global/.gitignore b/packages/@aws-cdk/aws-dynamodb-global/.gitignore deleted file mode 100644 index 46a4f14048e67..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -*.js -*.js.map -*.d.ts -node_modules -*.generated.ts -dist -tsconfig.json - -.jsii - -.LAST_BUILD -.nyc_output -coverage -nyc.config.js -.LAST_PACKAGE - -*.snk -!test/test.lambda.handler.js -!.eslintrc.js - -junit.xml -!jest.config.js -!**/*.snapshot/**/asset.*/*.js -!**/*.snapshot/**/asset.*/*.d.ts - -!**/*.snapshot/**/asset.*/** diff --git a/packages/@aws-cdk/aws-dynamodb-global/.npmignore b/packages/@aws-cdk/aws-dynamodb-global/.npmignore deleted file mode 100644 index 0dca9279d755b..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/.npmignore +++ /dev/null @@ -1,30 +0,0 @@ -# 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 -lambda-packages/aws-global-table-coordinator/node_modules - -*.tsbuildinfo - -tsconfig.json -.eslintrc.js - -# exclude cdk artifacts -**/cdk.out -junit.xml -test/ -!*.lit.ts -jest.config.js -**/*.snapshot diff --git a/packages/@aws-cdk/aws-dynamodb-global/LICENSE b/packages/@aws-cdk/aws-dynamodb-global/LICENSE deleted file mode 100644 index 9b722c65c5481..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/LICENSE +++ /dev/null @@ -1,201 +0,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 2018-2023 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-dynamodb-global/NOTICE b/packages/@aws-cdk/aws-dynamodb-global/NOTICE deleted file mode 100644 index a27b7dd317649..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-dynamodb-global/README.md b/packages/@aws-cdk/aws-dynamodb-global/README.md deleted file mode 100644 index 77f2725e76797..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# @aws-cdk/aws-dynamodb-global - - ---- - -![Deprecated](https://img.shields.io/badge/deprecated-critical.svg?style=for-the-badge) - -> This API may emit warnings. Backward compatibility is not guaranteed. - ---- - - - -## NOTICE: This module has been deprecated in favor of `@aws-cdk/aws-dynamodb.Table.replicationRegions` - ---- - -Global Tables builds upon DynamoDB’s global footprint to provide you with a fully managed, multi-region, and multi-master database that provides fast, local, read and write performance for massively scaled, global applications. Global Tables replicates your Amazon DynamoDB tables automatically across your choice of AWS regions. - -Here is a minimal deployable Global DynamoDB tables definition: - -```ts -import { AttributeType } from '@aws-cdk/aws-dynamodb'; -import { GlobalTable } from '@aws-cdk/aws-dynamodb-global'; -import { App } from '@aws-cdk/core'; - -const app = new App(); -new GlobalTable(app, 'globdynamodb', { - partitionKey: { name: 'hashKey', type: AttributeType.STRING }, - tableName: 'GlobalTable', - regions: [ "us-east-1", "us-east-2", "us-west-2" ], -}); -app.synth(); -``` - -## Implementation Notes - -AWS Global DynamoDB Tables is an odd case currently. The way this package works - - -* Creates a DynamoDB table in a separate stack in each `DynamoDBGlobalStackProps.region` specified -* Deploys a CFN Custom Resource to your stack's specified region that calls a lambda that runs the aws cli which calls `createGlobalTable()` - -### Notes - -GlobalTable() will set `dynamoProps.stream` to be `NEW_AND_OLD_IMAGES` since this is a required attribute for AWS Global DynamoDB tables to work. The package will throw an error if any other `stream` specification is set in `DynamoDBGlobalStackProps`. diff --git a/packages/@aws-cdk/aws-dynamodb-global/jest.config.js b/packages/@aws-cdk/aws-dynamodb-global/jest.config.js deleted file mode 100644 index 34818e1593f6b..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/jest.config.js +++ /dev/null @@ -1,2 +0,0 @@ -const baseConfig = require('../../../tools/@aws-cdk/cdk-build-tools/config/jest.config'); -module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/.no-packagejson-validator b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/.no-packagejson-validator deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/.gitignore b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/.gitignore deleted file mode 100644 index b50a1c9030545..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules/ - -dist -.LAST_PACKAGE -.LAST_BUILD -*.snk -!*.js \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/LICENSE b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/LICENSE deleted file mode 100644 index 9b722c65c5481..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/LICENSE +++ /dev/null @@ -1,201 +0,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 2018-2023 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-dynamodb-global/lambda-packages/aws-global-table-coordinator/NOTICE b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/NOTICE deleted file mode 100644 index a27b7dd317649..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/README.md b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/README.md deleted file mode 100644 index 3edabcb4c82cf..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/README.md +++ /dev/null @@ -1,2 +0,0 @@ -## CloudFormation Custom Resource for linking DynamoDB Global Tables -This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/jest.config.js b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/jest.config.js deleted file mode 100644 index 7e38dba6f3ba0..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/jest.config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - "roots": [ - "/lib", - "/test" - ], - "testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(ts|js)$", - "moduleFileExtensions": [ - "ts", - "tsx", - "js", - "jsx", - "json", - "node" - ], - "testEnvironment": "node" -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/lib/index.js b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/lib/index.js deleted file mode 100644 index 27732a5f5e9ac..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/lib/index.js +++ /dev/null @@ -1,164 +0,0 @@ -const AWS = require('aws-sdk'); - -// These are used for test purposes only -let defaultResponseURL; - -/** - * Upload a CloudFormation response for a Custom Resource - * - * @param {object} event the Lambda event payload received by the handler function - * @param {object} context the Lambda context received by the handler function - * @param {string} responseStatus the response status, either 'SUCCESS' or 'FAILED' - * @param {string} physicalResourceId CloudFormation physical resource ID - * @param {object} [responseData] arbitrary response data object - * @param {string} [reason] reason for failure, if any, to convey to the user - * @returns {Promise} Promise that is resolved on success, or rejected on connection error or HTTP error response - */ -let report = function (event, context, responseStatus, physicalResourceId, responseData, reason) { - return new Promise((resolve, reject) => { - const https = require('https'); - const { URL } = require('url'); - - var responseBody = JSON.stringify({ - Status: responseStatus, - Reason: reason, - PhysicalResourceId: physicalResourceId || context.logStreamName, - StackId: event.StackId, - RequestId: event.RequestId, - LogicalResourceId: event.LogicalResourceId, - Data: responseData - }); - - const parsedUrl = new URL(event.ResponseURL || defaultResponseURL); - const options = { - hostname: parsedUrl.hostname, - port: 443, - path: parsedUrl.pathname + parsedUrl.search, - method: 'PUT', - headers: { - 'Content-Type': '', - 'Content-Length': responseBody.length - } - }; - - https.request(options) - .on('error', reject) - .on('response', res => { - res.resume(); - if (res.statusCode >= 400) { - reject(new Error(`Server returned error ${res.statusCode}: ${res.statusMessage}`)); - } else { - resolve(); - } - }) - .end(responseBody, 'utf8'); - }); -}; -/** - * Lambda to handle linking together DynamoDB tables into a global table. - */ -exports.handler = async function (event, context) { - console.log("REQUEST RECEIVED:\n" + JSON.stringify(event)); - var responseData = {}; - var physicalResourceId; - - try { - switch (event.RequestType) { - case 'Create': - console.log("CREATE!"); - var dynamodb = new AWS.DynamoDB(); - var regions = []; - for (var i = 0; i < event.ResourceProperties.Regions.length; i++) { - regions.push({ - "RegionName": event.ResourceProperties.Regions[i] - }); - } - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicationGroup: regions - }; - console.log(params); - await dynamodb.createGlobalTable(params).promise(); - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - case 'Update': - console.log("UPDATE!"); - var dynamodb = new AWS.DynamoDB(); - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"] - }; - // Get the current regions deployed for this table - let data = await dynamodb.describeGlobalTable(params).promise(); - // Flatten the data - var currentDynamoRegions = []; - for (let region of data["GlobalTableDescription"]["ReplicationGroup"]) { - currentDynamoRegions.push(region["RegionName"]); - } - - // Build the params for regions to build - var addRegions = []; - for (var i = 0; i < event.ResourceProperties.Regions.length; i++) { - if(currentDynamoRegions.indexOf(event.ResourceProperties.Regions[i]) < 0 ){ - addRegions.push({ - Create: { - RegionName: String(event.ResourceProperties.Regions[i]) - } - }); - } - } - // Call AWS sdk to update DynamoDB to add the regions - console.log("Add Regions: "+ JSON.stringify(addRegions)); - if(addRegions.length > 0){ - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicaUpdates: addRegions - }; - console.log(params); - await dynamodb.updateGlobalTable(params).promise(); - } - - // Need to add/remove regions in separate steps - // Build the params for removing regions - var removeRegions = []; - for (var i = 0; i < currentDynamoRegions.length; i++) { - if(event.ResourceProperties.Regions.indexOf(currentDynamoRegions[i]) < 0 ){ - removeRegions.push({ - Delete: { - RegionName: String(currentDynamoRegions[i]) - } - }); - } - } - // Call AWS sdk to update DynamoDB to remove the regions - console.log("Remove Regions: "+ JSON.stringify(removeRegions)); - if(removeRegions.length > 0){ - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicaUpdates: removeRegions - }; - console.log(params); - await dynamodb.updateGlobalTable(params).promise(); - } - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - case 'Delete': - console.log("DELETE!"); - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - default: - throw new Error(`Unsupported request type ${event.RequestType}`); - } - - console.log(`Done!`); - } catch (err) { - console.log(`Caught error ${err}.`); - await report(event, context, 'FAILED', physicalResourceId, null, err.message); - } -}; - -/** - * @private - */ -exports.withDefaultResponseURL = function (url) { - defaultResponseURL = url; -}; diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json deleted file mode 100644 index eb0a05ac95760..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@aws-cdk/aws-global-lambda-coordinator", - "private": true, - "version": "0.0.0", - "description": "This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.", - "main": "lib/handler.js", - "directories": { - "test": "test" - }, - "scripts": { - "build": "echo No build", - "test": "jest", - "eslint": "eslint lib", - "build+test+package": "npm run build+test", - "build+test": "npm run build && npm test", - "build+test+extract": "npm run build+test", - "build+extract": "npm run build" - }, - "keywords": [ - "aws", - "cdk", - "dynamodb", - "global" - ], - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com", - "organization": true - }, - "license": "Apache-2.0", - "devDependencies": { - "aws-sdk": "^2.1317.0", - "aws-sdk-mock": "5.6.0", - "eslint": "^7.32.0", - "eslint-config-standard": "^14.1.1", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.3.1", - "eslint-plugin-standard": "^4.1.0", - "jest": "^27.5.1", - "lambda-tester": "^3.6.0", - "nock": "^13.3.0" - } -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/test/test.lambda.handler.js b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/test/test.lambda.handler.js deleted file mode 100644 index 0224911f727ec..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/test/test.lambda.handler.js +++ /dev/null @@ -1,139 +0,0 @@ -'use strict'; - -const handler = require('../lib'); -const AWS = require('aws-sdk-mock'); -const LambdaTester = require('lambda-tester').noVersionCheck(); -const sinon = require('sinon'); -const nock = require('nock'); - -AWS.setSDK(require.resolve('aws-sdk')); - -describe('Global DynamoDB Handler', () => { - const origLog = console.log; - const testRequestId = 'f4ef1b10-c39a-44e3-99c0-fbf7e53c3943'; - const testTableName = 'testTable'; - const ResponseURL = 'https://cloudwatch-response-mock.example.com/'; - - beforeEach(() => { - handler.withDefaultResponseURL(ResponseURL); - console.log = function () {}; - }); - afterEach(() => { - AWS.restore(); - console.log = origLog; - }); - - test('Fails if the event payload is empty', () => { - const request = nock(ResponseURL).put('/', body => { - return body.Status === 'FAILED' && body.Reason === 'Unsupported request type undefined'; - }).reply(200); - return LambdaTester(handler.handler) - .event({}) - .expectResolve(() => { - expect(request.isDone()).toBe(true); - }); - }); - - test('Fails if the request type is bogus', () => { - const bogusType = 'bogus'; - const request = nock(ResponseURL).put('/', body => { - return body.Status === 'FAILED' && body.Reason === 'Unsupported request type ' + bogusType; - }).reply(200); - return LambdaTester(handler.handler) - .event({ - RequestType: bogusType - }) - .expectResolve(() => { - expect(request.isDone()).toBe(true); - }); - }); - - test('Call createGlobalTable if RequestType is Create', () => { - const createTableFake = sinon.fake.resolves({ - GlobalTableDescription: { - GlobalTableName: testTableName, - ReplicationGroup: [{ RegionName: "us-west-2" }, { RegionName: "us-east-1" }] - } - }); - - AWS.mock('DynamoDB', 'createGlobalTable', createTableFake); - - const request = nock(ResponseURL).put('/', body => { - return body.Status === 'SUCCESS'; - }).reply(200); - - return LambdaTester(handler.handler) - .event({ - RequestType: 'Create', - RequestId: testRequestId, - ResourceProperties: { - TableName: testTableName, - Regions: [ 'us-west-2', 'us-east-1'] - } - }) - .expectResolve(() => { - sinon.assert.calledWith(createTableFake, sinon.match({ - GlobalTableName: testTableName, - ReplicationGroup: [{ RegionName: "us-west-2" }, { RegionName: "us-east-1" }] - })); - expect(request.isDone()).toBe(true); - }); - }); - - test('Call describeGlobalTable and updateGlobalTable if RequestType is Update', () => { - const describeTablesFake = sinon.fake.resolves({ - GlobalTableDescription: { - GlobalTableName: testTableName, - ReplicationGroup: [{ RegionName: 'us-west-2' }, { RegionName: 'us-east-2' }] - } - }); - - const updateTablesFake = sinon.fake.resolves({ - GlobalTableDescription: { - GlobalTableName: testTableName - } - }); - - AWS.mock('DynamoDB', 'describeGlobalTable', describeTablesFake); - AWS.mock('DynamoDB', 'updateGlobalTable', updateTablesFake); - - const request = nock(ResponseURL).put('/', body => { - return body.Status === 'SUCCESS'; - }).reply(200); - - return LambdaTester(handler.handler) - .event({ - RequestType: 'Update', - RequestId: testRequestId, - ResourceProperties: { - TableName: testTableName, - Regions: [ 'us-west-2', 'us-east-1'] - } - }) - .expectResolve(() => { - sinon.assert.calledWith(updateTablesFake, sinon.match({ - GlobalTableName: testTableName - })); - sinon.assert.calledWith(describeTablesFake, sinon.match({ - GlobalTableName: testTableName - })); - expect(request.isDone()).toBe(true); - }); - }); - - test('Do nothing if RequestType is Delete', () => { - const request = nock(ResponseURL).put('/', body => { - return body.Status === 'SUCCESS'; - }).reply(200); - - return LambdaTester(handler.handler) - .event({ - RequestType: 'Delete', - RequestId: testRequestId, - ResourceProperties: {} - }) - .expectResolve(() => { - expect(request.isDone()).toBe(true); - }); - }); -}); diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.ts deleted file mode 100644 index 576228502bb27..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/aws-dynamodb-global.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as dynamodb from '@aws-cdk/aws-dynamodb'; -import * as cdk from '@aws-cdk/core'; -import { Construct } from 'constructs'; -import { GlobalTableCoordinator } from './global-table-coordinator'; - -/** - * Properties for the multiple DynamoDB tables to mash together into a - * global table - */ -export interface GlobalTableProps extends cdk.StackProps, dynamodb.TableOptions { - /** - * Name of the DynamoDB table to use across all regional tables. - * This is required for global tables. - */ - readonly tableName: string; - - /** - * Array of environments to create DynamoDB tables in. - * The tables will all be created in the same account. - */ - readonly regions: string[]; -} - -/** - * This class works by deploying an AWS DynamoDB table into each region specified in GlobalTableProps.regions[], - * then triggering a CloudFormation Custom Resource Lambda to link them all together to create linked AWS Global DynamoDB tables. - * - * @deprecated use `@aws-cdk/aws-dynamodb.Table.replicationRegions` instead - */ -export class GlobalTable extends Construct { - /** - * Creates the cloudformation custom resource that launches a lambda to tie it all together - */ - private lambdaGlobalTableCoordinator: GlobalTableCoordinator; - - /** - * Creates dynamoDB tables across regions that will be able to be globbed together into a global table - */ - private readonly _regionalTables = new Array(); - - constructor(scope: Construct, id: string, props: GlobalTableProps) { - super(scope, id); - - cdk.Annotations.of(this).addWarning('The @aws-cdk/aws-dynamodb-global module has been deprecated in favor of @aws-cdk/aws-dynamodb.Table.replicationRegions'); - - this._regionalTables = []; - - if (props.stream != null && props.stream !== dynamodb.StreamViewType.NEW_AND_OLD_IMAGES) { - throw new Error('dynamoProps.stream MUST be set to dynamodb.StreamViewType.NEW_AND_OLD_IMAGES'); - } - - // need to set this stream specification, otherwise global tables don't work - // And no way to set a default value in an interface - const regionalTableProps: dynamodb.TableProps = { - ...props, - removalPolicy: props.removalPolicy, - stream: dynamodb.StreamViewType.NEW_AND_OLD_IMAGES, - }; - - this.lambdaGlobalTableCoordinator = new GlobalTableCoordinator(scope, id + '-CustomResource', props); - - const scopeStack = cdk.Stack.of(scope); - // here we loop through the configured regions. - // in each region we'll deploy a separate stack with a DynamoDB Table with identical properties in the individual stacks - for (const region of props.regions) { - const regionalStack = new cdk.Stack(this, id + '-' + region, { env: { region, account: scopeStack.account } }); - const regionalTable = new dynamodb.Table(regionalStack, `${id}-GlobalTable-${region}`, regionalTableProps); - this._regionalTables.push(regionalTable); - - // deploy the regional stack before the Lambda coordinator stack - this.lambdaGlobalTableCoordinator.addDependency(regionalStack); - } - } - - /** - * Obtain tables deployed in other each region - */ - public get regionalTables() { - return this._regionalTables.map(x => x); - } -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/global-table-coordinator.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/global-table-coordinator.ts deleted file mode 100644 index 89c751e7b7e44..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/global-table-coordinator.ts +++ /dev/null @@ -1,57 +0,0 @@ -import * as path from 'path'; -import * as iam from '@aws-cdk/aws-iam'; -import * as lambda from '@aws-cdk/aws-lambda'; -import * as cdk from '@aws-cdk/core'; -import { Construct } from 'constructs'; -import { GlobalTableProps } from './aws-dynamodb-global'; - -/** - * A stack that will make a Lambda that will launch a lambda to glue - * together all the DynamoDB tables into a global table - */ -export class GlobalTableCoordinator extends cdk.Stack { - constructor(scope: Construct, id: string, props: GlobalTableProps) { - super(scope, id, props); - const lambdaFunction = new lambda.SingletonFunction(this, 'SingletonLambda', { - code: lambda.Code.fromAsset(path.resolve(__dirname, '../', 'lambda-packages', 'aws-global-table-coordinator', 'lib')), - description: 'Lambda to make DynamoDB a global table', - handler: 'index.handler', - runtime: lambda.Runtime.NODEJS_14_X, - timeout: cdk.Duration.minutes(5), - uuid: 'D38B65A6-6B54-4FB6-9BAD-9CD40A6DAC12', - }); - - grantCreateGlobalTableLambda(lambdaFunction.role); - - new cdk.CustomResource(this, 'CfnCustomResource', { - serviceToken: lambdaFunction.functionArn, - pascalCaseProperties: true, - properties: { - regions: props.regions, - resourceType: 'Custom::DynamoGlobalTableCoordinator', - tableName: props.tableName, - }, - removalPolicy: props.removalPolicy, - }); - } -} - -/** - * Permits an IAM Principal to create a global dynamodb table. - * @param principal The principal (no-op if undefined) - */ -function grantCreateGlobalTableLambda(principal?: iam.IPrincipal): void { - if (principal) { - principal.addToPrincipalPolicy(new iam.PolicyStatement({ - resources: ['*'], - actions: [ - 'iam:CreateServiceLinkedRole', - 'application-autoscaling:DeleteScalingPolicy', - 'application-autoscaling:DeregisterScalableTarget', - 'dynamodb:CreateGlobalTable', 'dynamodb:DescribeLimits', - 'dynamodb:DeleteTable', 'dynamodb:DescribeGlobalTable', - 'dynamodb:UpdateGlobalTable', - ], - })); - } -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/lib/index.ts b/packages/@aws-cdk/aws-dynamodb-global/lib/index.ts deleted file mode 100644 index 021e076cc13f1..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './aws-dynamodb-global'; diff --git a/packages/@aws-cdk/aws-dynamodb-global/package.json b/packages/@aws-cdk/aws-dynamodb-global/package.json deleted file mode 100644 index 27ffb5bb1fce0..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/package.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "name": "@aws-cdk/aws-dynamodb-global", - "version": "0.0.0", - "private": true, - "description": "Build a global dynamodb table", - "deprecated": "This module has been deprecated. Use @aws-cdk/aws-dynamodb.Table with replicationRegions instead", - "license": "Apache-2.0", - "homepage": "https://github.com/aws/aws-cdk", - "repository": { - "type": "git", - "url": "https://github.com/aws/aws-cdk.git", - "directory": "packages/@aws-cdk/aws-dynamodb-global" - }, - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com", - "organization": true - }, - "jsii": { - "outdir": "dist", - "targets": { - "java": { - "package": "software.amazon.awscdk.services.dynamodb.global", - "maven": { - "groupId": "software.amazon.awscdk", - "artifactId": "dynamodb-global" - } - }, - "python": { - "distName": "aws-cdk.aws-dynamodb-global", - "module": "aws_cdk.aws_dynamodb_global", - "classifiers": [ - "Framework :: AWS CDK", - "Framework :: AWS CDK :: 2" - ] - }, - "dotnet": { - "namespace": "Amazon.CDK.AWS.DynamoDB.Global", - "packageId": "Amazon.CDK.AWS.DynamoDB.Global", - "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/main/logo/default-256-dark.png" - } - }, - "projectReferences": true, - "metadata": { - "jsii": { - "rosetta": { - "strict": true - } - } - } - }, - "keywords": [ - "aws", - "cdk", - "constructs", - "dynamodb", - "global" - ], - "dependencies": { - "@aws-cdk/aws-dynamodb": "0.0.0", - "@aws-cdk/aws-iam": "0.0.0", - "@aws-cdk/aws-lambda": "0.0.0", - "@aws-cdk/core": "0.0.0", - "constructs": "^10.0.0" - }, - "devDependencies": { - "@aws-cdk/assertions": "0.0.0", - "@aws-cdk/cdk-build-tools": "0.0.0", - "@aws-cdk/integ-runner": "0.0.0", - "@aws-cdk/pkglint": "0.0.0", - "@types/jest": "^27.5.2", - "jest": "^27.5.1" - }, - "peerDependencies": { - "@aws-cdk/aws-dynamodb": "0.0.0", - "@aws-cdk/aws-iam": "0.0.0", - "@aws-cdk/aws-lambda": "0.0.0", - "@aws-cdk/core": "0.0.0", - "constructs": "^10.0.0" - }, - "scripts": { - "build": "cdk-build", - "watch": "cdk-watch", - "lint": "cdk-lint", - "test": "cdk-test", - "integ": "integ-runner", - "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" - }, - "engines": { - "node": ">= 14.15.0" - }, - "main": "lib/index.js", - "types": "lib/index.d.ts", - "stability": "deprecated", - "awscdkio": { - "announce": false - }, - "maturity": "deprecated", - "publishConfig": { - "tag": "latest" - } -} diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/dynamodb-global.test.ts b/packages/@aws-cdk/aws-dynamodb-global/test/dynamodb-global.test.ts deleted file mode 100644 index 1d6f90d4a16ad..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/dynamodb-global.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import { Attribute, AttributeType, StreamViewType, Table } from '@aws-cdk/aws-dynamodb'; -import { describeDeprecated, testDeprecated } from '@aws-cdk/cdk-build-tools'; -import { App, CfnOutput, Stack } from '@aws-cdk/core'; -import { GlobalTable, GlobalTableProps } from '../lib'; - -/* eslint-disable quote-props */ - -// CDK parameters -const CONSTRUCT_NAME = 'aws-cdk-dynamodb-global'; - -// DynamoDB table parameters -const TABLE_NAME = 'GlobalTable'; -const TABLE_PARTITION_KEY: Attribute = { name: 'hashKey', type: AttributeType.STRING }; - -const STACK_PROPS: GlobalTableProps = { - partitionKey: TABLE_PARTITION_KEY, - tableName: TABLE_NAME, - regions: ['us-east-1', 'us-east-2', 'us-west-2'], -}; - -describeDeprecated('Default Global DynamoDB stack', () => { - test('global dynamo', () => { - const stack = new Stack(); - new GlobalTable(stack, CONSTRUCT_NAME, STACK_PROPS); - const topStack = stack.node.findChild(CONSTRUCT_NAME) as Stack; - for ( const reg of STACK_PROPS.regions ) { - const tableStack = topStack.node.findChild(CONSTRUCT_NAME + '-' + reg) as Stack; - Template.fromStack(tableStack).hasResourceProperties('AWS::DynamoDB::Table', { - 'KeySchema': [ - { - 'AttributeName': 'hashKey', - 'KeyType': 'HASH', - }, - ], - 'AttributeDefinitions': [ - { - 'AttributeName': 'hashKey', - 'AttributeType': 'S', - }, - ], - 'StreamSpecification': { - 'StreamViewType': 'NEW_AND_OLD_IMAGES', - }, - 'TableName': 'GlobalTable', - }); - } - const customResourceStack = stack.node.findChild(CONSTRUCT_NAME + '-CustomResource') as Stack; - Template.fromStack(customResourceStack).hasResourceProperties('AWS::Lambda::Function', { - Description: 'Lambda to make DynamoDB a global table', - Handler: 'index.handler', - Timeout: 300, - }); - Template.fromStack(customResourceStack).hasResourceProperties('AWS::CloudFormation::CustomResource', { - Regions: STACK_PROPS.regions, - ResourceType: 'Custom::DynamoGlobalTableCoordinator', - TableName: TABLE_NAME, - }); - }); -}); - -testDeprecated('GlobalTable generated stacks inherit their account from the parent stack', () => { - const app = new App({ context: { '@aws-cdk/core:stackRelativeExports': true } }); - const stack = new Stack(app, 'GlobalTableStack', { env: { account: '123456789012', region: 'us-east-1' } }); - - const globalTable = new GlobalTable(stack, CONSTRUCT_NAME, { - tableName: TABLE_NAME, - partitionKey: TABLE_PARTITION_KEY, - regions: ['us-east-1', 'us-west-2'], - stream: StreamViewType.NEW_AND_OLD_IMAGES, - }); - - new CfnOutput(stack, 'DynamoDbOutput', { - // this works, because both `stack` and `regionTables[0]` stack are in the same account & region - value: globalTable.regionalTables[0].tableStreamArn!, - }); - - Template.fromStack(stack).templateMatches({ - 'Outputs': { - 'DynamoDbOutput': { - 'Value': { - 'Fn::ImportValue': 'GlobalTableStackawscdkdynamodbglobalawscdkdynamodbglobaluseast19C1C8A14:ExportsOutputFnGetAttawscdkdynamodbglobalGlobalTableuseast1FC03DD69StreamArn9CE585ED', - }, - }, - }, - }); -}); - -describeDeprecated('Enforce StreamSpecification', () => { - test('global dynamo should only allow NEW_AND_OLD_IMAGES', () => { - const stack = new Stack(); - - expect(() => { - new GlobalTable(stack, CONSTRUCT_NAME, { - tableName: TABLE_NAME, - stream: StreamViewType.KEYS_ONLY, - partitionKey: TABLE_PARTITION_KEY, - regions: ['us-east-1', 'us-east-2', 'us-west-2'], - }); - }).toThrow(/dynamoProps.stream MUST be set to dynamodb.StreamViewType.NEW_AND_OLD_IMAGES/); - }); -}); - -describeDeprecated('Check getting tables', () => { - test('global dynamo should only allow NEW_AND_OLD_IMAGES', () => { - const stack = new Stack(); - const regTables = new GlobalTable(stack, CONSTRUCT_NAME, { - tableName: TABLE_NAME, - partitionKey: TABLE_PARTITION_KEY, - regions: ['us-east-1', 'us-east-2', 'us-west-2'], - }); - expect(regTables.regionalTables.length).toEqual(3); - for (const table of regTables.regionalTables) { - expect(table).toBeInstanceOf(Table); - } - }); -}); diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/Default.template.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/Default.template.json deleted file mode 100644 index 9e26dfeeb6e64..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/Default.template.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/asset.94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/index.js b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/asset.94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/index.js deleted file mode 100644 index 27732a5f5e9ac..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/asset.94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/index.js +++ /dev/null @@ -1,164 +0,0 @@ -const AWS = require('aws-sdk'); - -// These are used for test purposes only -let defaultResponseURL; - -/** - * Upload a CloudFormation response for a Custom Resource - * - * @param {object} event the Lambda event payload received by the handler function - * @param {object} context the Lambda context received by the handler function - * @param {string} responseStatus the response status, either 'SUCCESS' or 'FAILED' - * @param {string} physicalResourceId CloudFormation physical resource ID - * @param {object} [responseData] arbitrary response data object - * @param {string} [reason] reason for failure, if any, to convey to the user - * @returns {Promise} Promise that is resolved on success, or rejected on connection error or HTTP error response - */ -let report = function (event, context, responseStatus, physicalResourceId, responseData, reason) { - return new Promise((resolve, reject) => { - const https = require('https'); - const { URL } = require('url'); - - var responseBody = JSON.stringify({ - Status: responseStatus, - Reason: reason, - PhysicalResourceId: physicalResourceId || context.logStreamName, - StackId: event.StackId, - RequestId: event.RequestId, - LogicalResourceId: event.LogicalResourceId, - Data: responseData - }); - - const parsedUrl = new URL(event.ResponseURL || defaultResponseURL); - const options = { - hostname: parsedUrl.hostname, - port: 443, - path: parsedUrl.pathname + parsedUrl.search, - method: 'PUT', - headers: { - 'Content-Type': '', - 'Content-Length': responseBody.length - } - }; - - https.request(options) - .on('error', reject) - .on('response', res => { - res.resume(); - if (res.statusCode >= 400) { - reject(new Error(`Server returned error ${res.statusCode}: ${res.statusMessage}`)); - } else { - resolve(); - } - }) - .end(responseBody, 'utf8'); - }); -}; -/** - * Lambda to handle linking together DynamoDB tables into a global table. - */ -exports.handler = async function (event, context) { - console.log("REQUEST RECEIVED:\n" + JSON.stringify(event)); - var responseData = {}; - var physicalResourceId; - - try { - switch (event.RequestType) { - case 'Create': - console.log("CREATE!"); - var dynamodb = new AWS.DynamoDB(); - var regions = []; - for (var i = 0; i < event.ResourceProperties.Regions.length; i++) { - regions.push({ - "RegionName": event.ResourceProperties.Regions[i] - }); - } - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicationGroup: regions - }; - console.log(params); - await dynamodb.createGlobalTable(params).promise(); - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - case 'Update': - console.log("UPDATE!"); - var dynamodb = new AWS.DynamoDB(); - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"] - }; - // Get the current regions deployed for this table - let data = await dynamodb.describeGlobalTable(params).promise(); - // Flatten the data - var currentDynamoRegions = []; - for (let region of data["GlobalTableDescription"]["ReplicationGroup"]) { - currentDynamoRegions.push(region["RegionName"]); - } - - // Build the params for regions to build - var addRegions = []; - for (var i = 0; i < event.ResourceProperties.Regions.length; i++) { - if(currentDynamoRegions.indexOf(event.ResourceProperties.Regions[i]) < 0 ){ - addRegions.push({ - Create: { - RegionName: String(event.ResourceProperties.Regions[i]) - } - }); - } - } - // Call AWS sdk to update DynamoDB to add the regions - console.log("Add Regions: "+ JSON.stringify(addRegions)); - if(addRegions.length > 0){ - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicaUpdates: addRegions - }; - console.log(params); - await dynamodb.updateGlobalTable(params).promise(); - } - - // Need to add/remove regions in separate steps - // Build the params for removing regions - var removeRegions = []; - for (var i = 0; i < currentDynamoRegions.length; i++) { - if(event.ResourceProperties.Regions.indexOf(currentDynamoRegions[i]) < 0 ){ - removeRegions.push({ - Delete: { - RegionName: String(currentDynamoRegions[i]) - } - }); - } - } - // Call AWS sdk to update DynamoDB to remove the regions - console.log("Remove Regions: "+ JSON.stringify(removeRegions)); - if(removeRegions.length > 0){ - var params = { - GlobalTableName: event["ResourceProperties"]["TableName"], - ReplicaUpdates: removeRegions - }; - console.log(params); - await dynamodb.updateGlobalTable(params).promise(); - } - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - case 'Delete': - console.log("DELETE!"); - await report(event, context, 'SUCCESS', physicalResourceId, responseData); - break; - default: - throw new Error(`Unsupported request type ${event.RequestType}`); - } - - console.log(`Done!`); - } catch (err) { - console.log(`Caught error ${err}.`); - await report(event, context, 'FAILED', physicalResourceId, null, err.message); - } -}; - -/** - * @private - */ -exports.withDefaultResponseURL = function (url) { - defaultResponseURL = url; -}; diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/cdk.out b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/cdk.out deleted file mode 100644 index 90bef2e09ad39..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/cdk.out +++ /dev/null @@ -1 +0,0 @@ -{"version":"17.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegCustomResource.template.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegCustomResource.template.json deleted file mode 100644 index 14dce48530ac7..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegCustomResource.template.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "Resources": { - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810": { - "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" - ] - ] - } - ] - } - }, - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleDefaultPolicy6E7EDDB6": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "application-autoscaling:DeleteScalingPolicy", - "application-autoscaling:DeregisterScalableTarget", - "dynamodb:CreateGlobalTable", - "dynamodb:DeleteTable", - "dynamodb:DescribeGlobalTable", - "dynamodb:DescribeLimits", - "dynamodb:UpdateGlobalTable", - "iam:CreateServiceLinkedRole" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleDefaultPolicy6E7EDDB6", - "Roles": [ - { - "Ref": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810" - } - ] - } - }, - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC1233FDC96A": { - "Type": "AWS::Lambda::Function", - "Properties": { - "Code": { - "S3Bucket": { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3Bucket66843878" - }, - "S3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708" - } - ] - } - ] - } - ] - ] - } - }, - "Role": { - "Fn::GetAtt": [ - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810", - "Arn" - ] - }, - "Description": "Lambda to make DynamoDB a global table", - "Handler": "index.handler", - "Runtime": "nodejs14.x", - "Timeout": 300 - }, - "DependsOn": [ - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleDefaultPolicy6E7EDDB6", - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810" - ] - }, - "CfnCustomResource": { - "Type": "AWS::CloudFormation::CustomResource", - "Properties": { - "ServiceToken": { - "Fn::GetAtt": [ - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC1233FDC96A", - "Arn" - ] - }, - "Regions": [ - "us-east-1", - "us-east-2", - "us-west-2" - ], - "ResourceType": "Custom::DynamoGlobalTableCoordinator", - "TableName": "integrationtest" - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - }, - "Parameters": { - "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3Bucket66843878": { - "Type": "String", - "Description": "S3 bucket for asset \"94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a\"" - }, - "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708": { - "Type": "String", - "Description": "S3 key for asset version \"94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a\"" - }, - "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aArtifactHash5687D31D": { - "Type": "String", - "Description": "Artifact hash for asset \"94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a\"" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast11DF47AEF.template.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast11DF47AEF.template.json deleted file mode 100644 index 41a42ab818174..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast11DF47AEF.template.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "Resources": { - "globdynamodbintegGlobalTableuseast162596384": { - "Type": "AWS::DynamoDB::Table", - "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - } - ], - "AttributeDefinitions": [ - { - "AttributeName": "hashKey", - "AttributeType": "S" - } - ], - "ProvisionedThroughput": { - "ReadCapacityUnits": 5, - "WriteCapacityUnits": 5 - }, - "StreamSpecification": { - "StreamViewType": "NEW_AND_OLD_IMAGES" - }, - "TableName": "integrationtest" - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast23BC6B972.template.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast23BC6B972.template.json deleted file mode 100644 index 83713a044fc2e..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguseast23BC6B972.template.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "Resources": { - "globdynamodbintegGlobalTableuseast2EF897C2E": { - "Type": "AWS::DynamoDB::Table", - "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - } - ], - "AttributeDefinitions": [ - { - "AttributeName": "hashKey", - "AttributeType": "S" - } - ], - "ProvisionedThroughput": { - "ReadCapacityUnits": 5, - "WriteCapacityUnits": 5 - }, - "StreamSpecification": { - "StreamViewType": "NEW_AND_OLD_IMAGES" - }, - "TableName": "integrationtest" - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguswest2104B9501.template.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguswest2104B9501.template.json deleted file mode 100644 index 3b29e58a31e91..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/globdynamodbintegglobdynamodbinteguswest2104B9501.template.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "Resources": { - "globdynamodbintegGlobalTableuswest27374C2EA": { - "Type": "AWS::DynamoDB::Table", - "Properties": { - "KeySchema": [ - { - "AttributeName": "hashKey", - "KeyType": "HASH" - } - ], - "AttributeDefinitions": [ - { - "AttributeName": "hashKey", - "AttributeType": "S" - } - ], - "ProvisionedThroughput": { - "ReadCapacityUnits": 5, - "WriteCapacityUnits": 5 - }, - "StreamSpecification": { - "StreamViewType": "NEW_AND_OLD_IMAGES" - }, - "TableName": "integrationtest" - }, - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/integ.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/integ.json deleted file mode 100644 index 131114861eb78..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/integ.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": "20.0.0", - "testCases": { - "integ.dynamodb.global": { - "stacks": [ - "*" - ], - "diffAssets": false, - "stackUpdateWorkflow": true - } - }, - "synthContext": {}, - "enableLookups": false -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/manifest.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/manifest.json deleted file mode 100644 index a35612d80ce0c..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/manifest.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "version": "17.0.0", - "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, - "globdynamodbintegglobdynamodbinteguseast11DF47AEF": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/us-east-1", - "properties": { - "templateFile": "globdynamodbintegglobdynamodbinteguseast11DF47AEF.template.json", - "validateOnSynth": false - }, - "metadata": { - "/Default/globdynamodbinteg/globdynamodbinteg-us-east-1/globdynamodbinteg-GlobalTable-us-east-1": [ - { - "type": "aws:cdk:hasPhysicalName", - "data": { - "Ref": "globdynamodbintegGlobalTableuseast162596384" - } - } - ], - "/Default/globdynamodbinteg/globdynamodbinteg-us-east-1/globdynamodbinteg-GlobalTable-us-east-1/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "globdynamodbintegGlobalTableuseast162596384" - } - ] - }, - "displayName": "Default/globdynamodbinteg/globdynamodbinteg-us-east-1" - }, - "globdynamodbintegglobdynamodbinteguseast23BC6B972": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/us-east-2", - "properties": { - "templateFile": "globdynamodbintegglobdynamodbinteguseast23BC6B972.template.json", - "validateOnSynth": false - }, - "metadata": { - "/Default/globdynamodbinteg/globdynamodbinteg-us-east-2/globdynamodbinteg-GlobalTable-us-east-2": [ - { - "type": "aws:cdk:hasPhysicalName", - "data": { - "Ref": "globdynamodbintegGlobalTableuseast2EF897C2E" - } - } - ], - "/Default/globdynamodbinteg/globdynamodbinteg-us-east-2/globdynamodbinteg-GlobalTable-us-east-2/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "globdynamodbintegGlobalTableuseast2EF897C2E" - } - ] - }, - "displayName": "Default/globdynamodbinteg/globdynamodbinteg-us-east-2" - }, - "globdynamodbintegglobdynamodbinteguswest2104B9501": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/us-west-2", - "properties": { - "templateFile": "globdynamodbintegglobdynamodbinteguswest2104B9501.template.json", - "validateOnSynth": false - }, - "metadata": { - "/Default/globdynamodbinteg/globdynamodbinteg-us-west-2/globdynamodbinteg-GlobalTable-us-west-2": [ - { - "type": "aws:cdk:hasPhysicalName", - "data": { - "Ref": "globdynamodbintegGlobalTableuswest27374C2EA" - } - } - ], - "/Default/globdynamodbinteg/globdynamodbinteg-us-west-2/globdynamodbinteg-GlobalTable-us-west-2/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "globdynamodbintegGlobalTableuswest27374C2EA" - } - ] - }, - "displayName": "Default/globdynamodbinteg/globdynamodbinteg-us-west-2" - }, - "globdynamodbintegCustomResource": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "globdynamodbintegCustomResource.template.json", - "validateOnSynth": false - }, - "dependencies": [ - "globdynamodbintegglobdynamodbinteguseast11DF47AEF", - "globdynamodbintegglobdynamodbinteguseast23BC6B972", - "globdynamodbintegglobdynamodbinteguswest2104B9501" - ], - "metadata": { - "/Default/globdynamodbinteg-CustomResource": [ - { - "type": "aws:cdk:asset", - "data": { - "path": "asset.94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a", - "id": "94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a", - "packaging": "zip", - "sourceHash": "94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a", - "s3BucketParameter": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3Bucket66843878", - "s3KeyParameter": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708", - "artifactHashParameter": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aArtifactHash5687D31D" - } - } - ], - "/Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810" - } - ], - "/Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleDefaultPolicy6E7EDDB6" - } - ], - "/Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC1233FDC96A" - } - ], - "/Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/S3Bucket": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3Bucket66843878" - } - ], - "/Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/S3VersionKey": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708" - } - ], - "/Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/ArtifactHash": [ - { - "type": "aws:cdk:logicalId", - "data": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aArtifactHash5687D31D" - } - ], - "/Default/globdynamodbinteg-CustomResource/CfnCustomResource/Default": [ - { - "type": "aws:cdk:logicalId", - "data": "CfnCustomResource" - } - ] - }, - "displayName": "Default/globdynamodbinteg-CustomResource" - }, - "Default": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "Default.template.json", - "validateOnSynth": false - }, - "metadata": { - "/Default/globdynamodbinteg": [ - { - "type": "aws:cdk:warning", - "data": "The @aws-cdk/aws-dynamodb-global module has been deprecated in favor of @aws-cdk/aws-dynamodb.Table.replicationRegions" - } - ] - }, - "displayName": "Default" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/tree.json b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/tree.json deleted file mode 100644 index 172addeea20d0..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.js.snapshot/tree.json +++ /dev/null @@ -1,498 +0,0 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.0.9" - } - }, - "Default": { - "id": "Default", - "path": "Default", - "children": { - "globdynamodbinteg": { - "id": "globdynamodbinteg", - "path": "Default/globdynamodbinteg", - "children": { - "globdynamodbinteg-us-east-1": { - "id": "globdynamodbinteg-us-east-1", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-1", - "children": { - "globdynamodbinteg-GlobalTable-us-east-1": { - "id": "globdynamodbinteg-GlobalTable-us-east-1", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-1/globdynamodbinteg-GlobalTable-us-east-1", - "children": { - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-1/globdynamodbinteg-GlobalTable-us-east-1/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", - "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - } - ], - "attributeDefinitions": [ - { - "attributeName": "hashKey", - "attributeType": "S" - } - ], - "provisionedThroughput": { - "readCapacityUnits": 5, - "writeCapacityUnits": 5 - }, - "streamSpecification": { - "streamViewType": "NEW_AND_OLD_IMAGES" - }, - "tableName": "integrationtest" - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", - "version": "0.0.0" - } - }, - "ScalingRole": { - "id": "ScalingRole", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-1/globdynamodbinteg-GlobalTable-us-east-1/ScalingRole", - "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - }, - "globdynamodbinteg-us-east-2": { - "id": "globdynamodbinteg-us-east-2", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-2", - "children": { - "globdynamodbinteg-GlobalTable-us-east-2": { - "id": "globdynamodbinteg-GlobalTable-us-east-2", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-2/globdynamodbinteg-GlobalTable-us-east-2", - "children": { - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-2/globdynamodbinteg-GlobalTable-us-east-2/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", - "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - } - ], - "attributeDefinitions": [ - { - "attributeName": "hashKey", - "attributeType": "S" - } - ], - "provisionedThroughput": { - "readCapacityUnits": 5, - "writeCapacityUnits": 5 - }, - "streamSpecification": { - "streamViewType": "NEW_AND_OLD_IMAGES" - }, - "tableName": "integrationtest" - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", - "version": "0.0.0" - } - }, - "ScalingRole": { - "id": "ScalingRole", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-east-2/globdynamodbinteg-GlobalTable-us-east-2/ScalingRole", - "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - }, - "globdynamodbinteg-us-west-2": { - "id": "globdynamodbinteg-us-west-2", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-west-2", - "children": { - "globdynamodbinteg-GlobalTable-us-west-2": { - "id": "globdynamodbinteg-GlobalTable-us-west-2", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-west-2/globdynamodbinteg-GlobalTable-us-west-2", - "children": { - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-west-2/globdynamodbinteg-GlobalTable-us-west-2/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", - "aws:cdk:cloudformation:props": { - "keySchema": [ - { - "attributeName": "hashKey", - "keyType": "HASH" - } - ], - "attributeDefinitions": [ - { - "attributeName": "hashKey", - "attributeType": "S" - } - ], - "provisionedThroughput": { - "readCapacityUnits": 5, - "writeCapacityUnits": 5 - }, - "streamSpecification": { - "streamViewType": "NEW_AND_OLD_IMAGES" - }, - "tableName": "integrationtest" - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.CfnTable", - "version": "0.0.0" - } - }, - "ScalingRole": { - "id": "ScalingRole", - "path": "Default/globdynamodbinteg/globdynamodbinteg-us-west-2/globdynamodbinteg-GlobalTable-us-west-2/ScalingRole", - "constructInfo": { - "fqn": "@aws-cdk/core.Resource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb.Table", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-dynamodb-global.GlobalTable", - "version": "0.0.0" - } - }, - "globdynamodbinteg-CustomResource": { - "id": "globdynamodbinteg-CustomResource", - "path": "Default/globdynamodbinteg-CustomResource", - "children": { - "SingletonLambda": { - "id": "SingletonLambda", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambda", - "constructInfo": { - "fqn": "@aws-cdk/aws-lambda.SingletonFunction", - "version": "0.0.0" - } - }, - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12": { - "id": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12", - "children": { - "ServiceRole": { - "id": "ServiceRole", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole", - "children": { - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Role", - "aws:cdk:cloudformation:props": { - "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" - ] - ] - } - ] - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnRole", - "version": "0.0.0" - } - }, - "DefaultPolicy": { - "id": "DefaultPolicy", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole/DefaultPolicy", - "children": { - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/ServiceRole/DefaultPolicy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::IAM::Policy", - "aws:cdk:cloudformation:props": { - "policyDocument": { - "Statement": [ - { - "Action": [ - "application-autoscaling:DeleteScalingPolicy", - "application-autoscaling:DeregisterScalableTarget", - "dynamodb:CreateGlobalTable", - "dynamodb:DeleteTable", - "dynamodb:DescribeGlobalTable", - "dynamodb:DescribeLimits", - "dynamodb:UpdateGlobalTable", - "iam:CreateServiceLinkedRole" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "policyName": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleDefaultPolicy6E7EDDB6", - "roles": [ - { - "Ref": "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810" - } - ] - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.CfnPolicy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Policy", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-iam.Role", - "version": "0.0.0" - } - }, - "Code": { - "id": "Code", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/Code", - "children": { - "Stage": { - "id": "Stage", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/Code/Stage", - "constructInfo": { - "fqn": "@aws-cdk/core.AssetStaging", - "version": "0.0.0" - } - }, - "AssetBucket": { - "id": "AssetBucket", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/Code/AssetBucket", - "constructInfo": { - "fqn": "@aws-cdk/aws-s3.BucketBase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-s3-assets.Asset", - "version": "0.0.0" - } - }, - "Resource": { - "id": "Resource", - "path": "Default/globdynamodbinteg-CustomResource/SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::Lambda::Function", - "aws:cdk:cloudformation:props": { - "code": { - "s3Bucket": { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3Bucket66843878" - }, - "s3Key": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "AssetParameters94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3aS3VersionKey14680708" - } - ] - } - ] - } - ] - ] - } - }, - "role": { - "Fn::GetAtt": [ - "SingletonLambdaD38B65A66B544FB69BAD9CD40A6DAC12ServiceRoleD9686810", - "Arn" - ] - }, - "description": "Lambda to make DynamoDB a global table", - "handler": "index.handler", - "runtime": "nodejs12.x", - "timeout": 300 - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-lambda.CfnFunction", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-lambda.Function", - "version": "0.0.0" - } - }, - "AssetParameters": { - "id": "AssetParameters", - "path": "Default/globdynamodbinteg-CustomResource/AssetParameters", - "children": { - "94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a": { - "id": "94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a", - "path": "Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a", - "children": { - "S3Bucket": { - "id": "S3Bucket", - "path": "Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/S3Bucket", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "S3VersionKey": { - "id": "S3VersionKey", - "path": "Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/S3VersionKey", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "ArtifactHash": { - "id": "ArtifactHash", - "path": "Default/globdynamodbinteg-CustomResource/AssetParameters/94575de3fd18404e41e94a6c1d4b7a1eec2985fd23d2c11999d095e09667ba3a/ArtifactHash", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.0.9" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.0.9" - } - }, - "CfnCustomResource": { - "id": "CfnCustomResource", - "path": "Default/globdynamodbinteg-CustomResource/CfnCustomResource", - "children": { - "Default": { - "id": "Default", - "path": "Default/globdynamodbinteg-CustomResource/CfnCustomResource/Default", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnResource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.CustomResource", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.App", - "version": "0.0.0" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.ts b/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.ts deleted file mode 100644 index 85ecc746b8ae5..0000000000000 --- a/packages/@aws-cdk/aws-dynamodb-global/test/integ.dynamodb.global.ts +++ /dev/null @@ -1,24 +0,0 @@ -/// !cdk-integ * -import { AttributeType } from '@aws-cdk/aws-dynamodb'; -import { App, RemovalPolicy, Stack } from '@aws-cdk/core'; -import { GlobalTable } from '../lib'; - -const app = new App(); -const stack = new Stack(app, 'Default'); - -const deprecated = process.env.JSII_DEPRECATED; -process.env.JSII_DEPRECATED = 'quiet'; - -new GlobalTable(stack, 'globdynamodbinteg', { - partitionKey: { name: 'hashKey', type: AttributeType.STRING }, - tableName: 'integrationtest', - regions: ['us-east-1', 'us-east-2', 'us-west-2'], - removalPolicy: RemovalPolicy.DESTROY, -}); -app.synth(); - -if (deprecated) { - process.env.JSII_DEPRECATED = deprecated; -} else { - delete process.env.JSII_DEPRECATED; -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index 8a335fd2b0fc7..3270864374893 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -86,10 +86,10 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "@types/sinon": "^9.0.11", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1", "sinon": "^9.2.4", diff --git a/packages/@aws-cdk/aws-ec2/lib/launch-template.ts b/packages/@aws-cdk/aws-ec2/lib/launch-template.ts index 24e7424bfeb93..0f27c58240c44 100644 --- a/packages/@aws-cdk/aws-ec2/lib/launch-template.ts +++ b/packages/@aws-cdk/aws-ec2/lib/launch-template.ts @@ -12,7 +12,9 @@ import { TagType, Tags, Token, + FeatureFlags, } from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import { Connections, IConnectable } from './connections'; import { CfnLaunchTemplate } from './ec2.generated'; @@ -591,8 +593,19 @@ export class LaunchTemplate extends Resource implements ILaunchTemplate, iam.IGr }, }); - if (props.userData) { - this.userData = props.userData; + const imageConfig: MachineImageConfig | undefined = props.machineImage?.getImage(this); + if (imageConfig) { + this.osType = imageConfig.osType; + this.imageId = imageConfig.imageId; + } + + if (FeatureFlags.of(this).isEnabled(cxapi.EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA)) { + // priority: prop.userData -> userData from machineImage -> undefined + this.userData = props.userData ?? imageConfig?.userData; + } else { + if (props.userData) { + this.userData = props.userData; + } } const userDataToken = Lazy.string({ produce: () => { @@ -603,12 +616,6 @@ export class LaunchTemplate extends Resource implements ILaunchTemplate, iam.IGr }, }); - const imageConfig: MachineImageConfig | undefined = props.machineImage?.getImage(this); - if (imageConfig) { - this.osType = imageConfig.osType; - this.imageId = imageConfig.imageId; - } - this.instanceType = props.instanceType; let marketOptions: any = undefined; diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index f20feee08f5c9..3f1949aeba9a6 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json index 1d2e86648cf93..57e75754f5e88 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/LambdaTestDefaultTestDeployAssert1AF2B360.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.template.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.template.json deleted file mode 100644 index 3a078b81f8fc5..0000000000000 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.template.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "Resources": { - "LTC4631592": { - "Type": "AWS::EC2::LaunchTemplate", - "Properties": { - "LaunchTemplateData": { - "MetadataOptions": { - "HttpEndpoint": "enabled", - "HttpProtocolIpv6": "enabled", - "HttpPutResponseHopLimit": 2, - "HttpTokens": "required", - "InstanceMetadataTags": "enabled" - }, - "TagSpecifications": [ - { - "ResourceType": "instance", - "Tags": [ - { - "Key": "Name", - "Value": "TestStack/LT" - } - ] - }, - { - "ResourceType": "volume", - "Tags": [ - { - "Key": "Name", - "Value": "TestStack/LT" - } - ] - } - ] - }, - "TagSpecifications": [ - { - "ResourceType": "launch-template", - "Tags": [ - { - "Key": "Name", - "Value": "TestStack/LT" - } - ] - } - ] - } - } - }, - "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/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.assets.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.assets.json index 9ed72b653b653..dac10038e94d8 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.assets.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { - "ea313fee581c8e898c158e9d123dd48345192689bb08a3f7e84716db61247c6c": { + "534a1fbecaccb7e2a071086c8085be5c15b2501781767cdeddf754fe3a0ceecb": { "source": { "path": "aws-cdk-ec2-lt-metadata-1.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "ea313fee581c8e898c158e9d123dd48345192689bb08a3f7e84716db61247c6c.json", + "objectKey": "534a1fbecaccb7e2a071086c8085be5c15b2501781767cdeddf754fe3a0ceecb.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.template.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.template.json index 3ff46f6e06e20..83f874269b6db 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.template.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/aws-cdk-ec2-lt-metadata-1.template.json @@ -44,9 +44,57 @@ } ] } + }, + "LTWithMachineImageAAC227A5": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "TagSpecifications": [ + { + "ResourceType": "launch-template", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + } + ] + } } }, "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" + }, "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", "Default": "/cdk-bootstrap/hnb659fds/version", diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/cdk.out index 8ecc185e9dbee..145739f539580 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/integ.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/integ.json index 92f821d9eb880..d0325b9f439fc 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "22.0.0", "testCases": { "LambdaTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/manifest.json index ac57774761bca..2a95821bd2fc1 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-ec2-lt-metadata-1.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/ea313fee581c8e898c158e9d123dd48345192689bb08a3f7e84716db61247c6c.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/534a1fbecaccb7e2a071086c8085be5c15b2501781767cdeddf754fe3a0ceecb.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -45,6 +39,18 @@ "data": "LTC4631592" } ], + "/aws-cdk-ec2-lt-metadata-1/LTWithMachineImage/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LTWithMachineImageAAC227A5" + } + ], + "/aws-cdk-ec2-lt-metadata-1/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], "/aws-cdk-ec2-lt-metadata-1/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -106,6 +112,12 @@ ] }, "displayName": "LambdaTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/tree.json b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/tree.json index 36dbaccbedb90..96da980720391 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.108" - } - }, "aws-cdk-ec2-lt-metadata-1": { "id": "aws-cdk-ec2-lt-metadata-1", "path": "aws-cdk-ec2-lt-metadata-1", @@ -69,15 +61,109 @@ } }, "constructInfo": { - "fqn": "@aws-cdk/core.CfnResource", + "fqn": "@aws-cdk/aws-ec2.CfnLaunchTemplate", "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.LaunchTemplate", + "version": "0.0.0" + } + }, + "LTWithMachineImage": { + "id": "LTWithMachineImage", + "path": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::LaunchTemplate", + "aws:cdk:cloudformation:props": { + "launchTemplateData": { + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "tagSpecifications": [ + { + "resourceType": "instance", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + }, + { + "resourceType": "volume", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "tagSpecifications": [ + { + "resourceType": "launch-template", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-ec2-lt-metadata-1/LTWithMachineImage" + } + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnLaunchTemplate", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.LaunchTemplate", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "aws-cdk-ec2-lt-metadata-1/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "aws-cdk-ec2-lt-metadata-1/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", "constructInfo": { "fqn": "@aws-cdk/core.Resource", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-ec2-lt-metadata-1/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-ec2-lt-metadata-1/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -98,12 +184,30 @@ "path": "LambdaTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.108" + "version": "10.1.189" } }, "DeployAssert": { "id": "DeployAssert", "path": "LambdaTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "LambdaTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "LambdaTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -120,6 +224,14 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.ts b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.ts index 5ee628b4bacdc..ba56a75edd4d5 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.ts +++ b/packages/@aws-cdk/aws-ec2/test/integ.launch-template.ts @@ -15,10 +15,14 @@ new ec2.LaunchTemplate(stack, 'LT', { instanceMetadataTags: true, }); +new ec2.LaunchTemplate(stack, 'LTWithMachineImage', { + machineImage: ec2.MachineImage.latestAmazonLinux({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + }), +}); new integ.IntegTest(app, 'LambdaTest', { testCases: [stack], }); app.synth(); - diff --git a/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts b/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts index 74ec38e098019..234d6558bbca2 100644 --- a/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/launch-template.test.ts @@ -12,6 +12,7 @@ import { Stack, Tags, } from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; import { stringLike } from './util'; import { AmazonLinuxImage, @@ -367,6 +368,44 @@ describe('LaunchTemplate', () => { }); }); + describe('feature flag @aws-cdk/aws-ec2:launchTemplateDefaultUserData', () => { + test('Given machineImage (Linux)', () => { + // WHEN + stack.node.setContext(cxapi.EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA, true); + const template = new LaunchTemplate(stack, 'Template', { + machineImage: new AmazonLinuxImage(), + }); + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: { + ImageId: { + Ref: stringLike('SsmParameterValueawsserviceamiamazonlinuxlatestamznami.*Parameter'), + }, + }, + }); + expect(template.osType).toBe(OperatingSystemType.LINUX); + expect(template.userData).toBeDefined(); + }); + + test('Given machineImage (Windows)', () => { + // WHEN + stack.node.setContext(cxapi.EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA, true); + const template = new LaunchTemplate(stack, 'Template', { + machineImage: new WindowsImage(WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE), + }); + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EC2::LaunchTemplate', { + LaunchTemplateData: { + ImageId: { + Ref: stringLike('SsmParameterValueawsserviceamiwindowslatestWindowsServer2019EnglishFullBase.*Parameter'), + }, + }, + }); + expect(template.osType).toBe(OperatingSystemType.WINDOWS); + expect(template.userData).toBeDefined(); + }); + }); + test.each([ [CpuCredits.STANDARD, 'standard'], [CpuCredits.UNLIMITED, 'unlimited'], @@ -901,6 +940,5 @@ describe('LaunchTemplate metadataOptions', () => { }, }, }); - }); }); diff --git a/packages/@aws-cdk/aws-ecr-assets/lib/tarball-asset.ts b/packages/@aws-cdk/aws-ecr-assets/lib/tarball-asset.ts index 32603cf7664b6..95dbbee1d1119 100644 --- a/packages/@aws-cdk/aws-ecr-assets/lib/tarball-asset.ts +++ b/packages/@aws-cdk/aws-ecr-assets/lib/tarball-asset.ts @@ -77,7 +77,7 @@ export class TarballImageAsset extends Construct implements IAsset { executable: [ 'sh', '-c', - `docker load -i ${relativePathInOutDir} | sed "s/Loaded image: //g"`, + `docker load -i ${relativePathInOutDir} | tail -n 1 | sed "s/Loaded image: //g"`, ], }); diff --git a/packages/@aws-cdk/aws-ecr-assets/package.json b/packages/@aws-cdk/aws-ecr-assets/package.json index cb90917e0511b..fe5a11e20b6ba 100644 --- a/packages/@aws-cdk/aws-ecr-assets/package.json +++ b/packages/@aws-cdk/aws-ecr-assets/package.json @@ -76,6 +76,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", diff --git a/packages/@aws-cdk/aws-ecr-assets/test/demo-tarball-hello-world/hello-world.tar b/packages/@aws-cdk/aws-ecr-assets/test/demo-tarball-hello-world/hello-world.tar new file mode 100644 index 0000000000000..2e9b55a25a8a7 Binary files /dev/null and b/packages/@aws-cdk/aws-ecr-assets/test/demo-tarball-hello-world/hello-world.tar differ diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.assets.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.assets.json new file mode 100644 index 0000000000000..19e97d96f3815 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "LoadFromTarballDefaultTestDeployAssert46673615.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/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.template.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/LoadFromTarballDefaultTestDeployAssert46673615.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/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/asset.a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474.tar b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/asset.a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474.tar new file mode 100644 index 0000000000000..2e9b55a25a8a7 Binary files /dev/null and b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/asset.a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474.tar differ diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/cdk.out new file mode 100644 index 0000000000000..145739f539580 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.assets.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.assets.json new file mode 100644 index 0000000000000..ad93a80114888 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.assets.json @@ -0,0 +1,36 @@ +{ + "version": "22.0.0", + "files": { + "7e85363095650cdc9e77b849e3afda82da3123dd43f5d237b9601f816ddf583e": { + "source": { + "path": "integ-assets-tarball.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "7e85363095650cdc9e77b849e3afda82da3123dd43f5d237b9601f816ddf583e.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": { + "a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474": { + "source": { + "executable": [ + "sh", + "-c", + "docker load -i asset.a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474.tar | tail -n 1 | sed \"s/Loaded image: //g\"" + ] + }, + "destinations": { + "current_account-current_region": { + "repositoryName": "cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}", + "imageTag": "a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-image-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.template.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.template.json new file mode 100644 index 0000000000000..a79e4296debea --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ-assets-tarball.template.json @@ -0,0 +1,105 @@ +{ + "Resources": { + "MyUserDC45028B": { + "Type": "AWS::IAM::User" + }, + "MyUserDefaultPolicy7B897426": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:GetDownloadUrlForLayer" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":repository/", + { + "Fn::Sub": "cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyUserDefaultPolicy7B897426", + "Users": [ + { + "Ref": "MyUserDC45028B" + } + ] + } + } + }, + "Outputs": { + "ImageUri": { + "Value": { + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474" + } + }, + "ImageUri2": { + "Value": { + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:a5fbe3aa4a0e49fac7d3fbe7b913cf022d307bfad6ef1e88e06cc2a229523474" + } + } + }, + "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/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ.json new file mode 100644 index 0000000000000..0f4dded2efe13 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "22.0.0", + "testCases": { + "LoadFromTarball/DefaultTest": { + "stacks": [ + "integ-assets-tarball" + ], + "assertionStack": "LoadFromTarball/DefaultTest/DeployAssert", + "assertionStackName": "LoadFromTarballDefaultTestDeployAssert46673615" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/manifest.json new file mode 100644 index 0000000000000..f5c1d20d76c84 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/manifest.json @@ -0,0 +1,129 @@ +{ + "version": "22.0.0", + "artifacts": { + "integ-assets-tarball.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integ-assets-tarball.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integ-assets-tarball": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integ-assets-tarball.template.json", + "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}/7e85363095650cdc9e77b849e3afda82da3123dd43f5d237b9601f816ddf583e.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integ-assets-tarball.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": [ + "integ-assets-tarball.assets" + ], + "metadata": { + "/integ-assets-tarball/MyUser/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyUserDC45028B" + } + ], + "/integ-assets-tarball/MyUser/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyUserDefaultPolicy7B897426" + } + ], + "/integ-assets-tarball/ImageUri": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageUri" + } + ], + "/integ-assets-tarball/ImageUri2": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageUri2" + } + ], + "/integ-assets-tarball/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-assets-tarball/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-assets-tarball" + }, + "LoadFromTarballDefaultTestDeployAssert46673615.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "LoadFromTarballDefaultTestDeployAssert46673615.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "LoadFromTarballDefaultTestDeployAssert46673615": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "LoadFromTarballDefaultTestDeployAssert46673615.template.json", + "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": [ + "LoadFromTarballDefaultTestDeployAssert46673615.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": [ + "LoadFromTarballDefaultTestDeployAssert46673615.assets" + ], + "metadata": { + "/LoadFromTarball/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/LoadFromTarball/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "LoadFromTarball/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/tree.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/tree.json new file mode 100644 index 0000000000000..3c7e326c73b0d --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.js.snapshot/tree.json @@ -0,0 +1,261 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "integ-assets-tarball": { + "id": "integ-assets-tarball", + "path": "integ-assets-tarball", + "children": { + "DockerImage": { + "id": "DockerImage", + "path": "integ-assets-tarball/DockerImage", + "children": { + "Staging": { + "id": "Staging", + "path": "integ-assets-tarball/DockerImage/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Repository": { + "id": "Repository", + "path": "integ-assets-tarball/DockerImage/Repository", + "constructInfo": { + "fqn": "@aws-cdk/aws-ecr.RepositoryBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ecr-assets.TarballImageAsset", + "version": "0.0.0" + } + }, + "DockerImage2": { + "id": "DockerImage2", + "path": "integ-assets-tarball/DockerImage2", + "children": { + "Staging": { + "id": "Staging", + "path": "integ-assets-tarball/DockerImage2/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Repository": { + "id": "Repository", + "path": "integ-assets-tarball/DockerImage2/Repository", + "constructInfo": { + "fqn": "@aws-cdk/aws-ecr.RepositoryBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ecr-assets.TarballImageAsset", + "version": "0.0.0" + } + }, + "MyUser": { + "id": "MyUser", + "path": "integ-assets-tarball/MyUser", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-assets-tarball/MyUser/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::User", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnUser", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "integ-assets-tarball/MyUser/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "integ-assets-tarball/MyUser/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "ecr:BatchCheckLayerAvailability", + "ecr:BatchGetImage", + "ecr:GetDownloadUrlForLayer" + ], + "Effect": "Allow", + "Resource": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":ecr:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":repository/", + { + "Fn::Sub": "cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}" + } + ] + ] + } + }, + { + "Action": "ecr:GetAuthorizationToken", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyUserDefaultPolicy7B897426", + "users": [ + { + "Ref": "MyUserDC45028B" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.User", + "version": "0.0.0" + } + }, + "ImageUri": { + "id": "ImageUri", + "path": "integ-assets-tarball/ImageUri", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "ImageUri2": { + "id": "ImageUri2", + "path": "integ-assets-tarball/ImageUri2", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-assets-tarball/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-assets-tarball/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "LoadFromTarball": { + "id": "LoadFromTarball", + "path": "LoadFromTarball", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "LoadFromTarball/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "LoadFromTarball/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "LoadFromTarball/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "LoadFromTarball/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "LoadFromTarball/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.ts b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.ts new file mode 100644 index 0000000000000..472d512369067 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-tarball.ts @@ -0,0 +1,29 @@ +import * as path from 'path'; +import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import * as assets from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'integ-assets-tarball'); + +const asset = new assets.TarballImageAsset(stack, 'DockerImage', { + tarballFile: path.join(__dirname, 'demo-tarball-hello-world/hello-world.tar'), +}); + +const asset2 = new assets.TarballImageAsset(stack, 'DockerImage2', { + tarballFile: path.join(__dirname, 'demo-tarball-hello-world/hello-world.tar'), +}); + +const user = new iam.User(stack, 'MyUser'); +asset.repository.grantPull(user); +asset2.repository.grantPull(user); + +new cdk.CfnOutput(stack, 'ImageUri', { value: asset.imageUri }); +new cdk.CfnOutput(stack, 'ImageUri2', { value: asset2.imageUri }); + +new IntegTest(app, 'LoadFromTarball', { + testCases: [ + stack, + ], +}); diff --git a/packages/@aws-cdk/aws-ecr-assets/test/tarball-asset.test.ts b/packages/@aws-cdk/aws-ecr-assets/test/tarball-asset.test.ts index 1333cc8e5c91b..e06d84eb31534 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/tarball-asset.test.ts +++ b/packages/@aws-cdk/aws-ecr-assets/test/tarball-asset.test.ts @@ -42,7 +42,7 @@ describe('image asset', () => { executable: [ 'sh', '-c', - `docker load -i asset.${asset.assetHash}.tar | sed "s/Loaded image: //g"`, + `docker load -i asset.${asset.assetHash}.tar | tail -n 1 | sed "s/Loaded image: //g"`, ], }, ); diff --git a/packages/@aws-cdk/aws-ecr/package.json b/packages/@aws-cdk/aws-ecr/package.json index 3246b55d8dfaf..12125c1ca334b 100644 --- a/packages/@aws-cdk/aws-ecr/package.json +++ b/packages/@aws-cdk/aws-ecr/package.json @@ -87,6 +87,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2" diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/aws-ecr-integ-stack.assets.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/aws-ecr-integ-stack.assets.json index d8e0a2d47b669..c6ae5f14f7ac3 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/aws-ecr-integ-stack.assets.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/aws-ecr-integ-stack.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "26df443ecb3d9a917feccf0349d0f8852c227c138904499fe5e26de6a090654c": { "source": { diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets.json new file mode 100644 index 0000000000000..8fd843ce656f5 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.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/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.template.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.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/aws-ecr/test/integ.basic.js.snapshot/integ.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/integ.json index bd0beb2b5c2df..0e898c63ccb23 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.basic": { + "cdk-ecr-integ-test-basic/DefaultTest": { "stacks": [ "aws-ecr-integ-stack" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-ecr-integ-test-basic/DefaultTest/DeployAssert", + "assertionStackName": "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/manifest.json index 4091ca05e21ad..fc9bbb2d7138c 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-ecr-integ-stack.assets": { "type": "cdk:asset-manifest", "properties": { @@ -65,6 +59,59 @@ ] }, "displayName": "aws-ecr-integ-stack" + }, + "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.template.json", + "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": [ + "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.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": [ + "cdkecrintegtestbasicDefaultTestDeployAssert4F7FBFB4.assets" + ], + "metadata": { + "/cdk-ecr-integ-test-basic/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-ecr-integ-test-basic/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-ecr-integ-test-basic/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/tree.json b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/tree.json index 9991d87ab8adc..64255404444da 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-ecr-integ-stack": { "id": "aws-ecr-integ-stack", "path": "aws-ecr-integ-stack", @@ -46,20 +38,98 @@ "id": "RepositoryURI", "path": "aws-ecr-integ-stack/RepositoryURI", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-ecr-integ-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-ecr-integ-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-ecr-integ-test-basic": { + "id": "cdk-ecr-integ-test-basic", + "path": "cdk-ecr-integ-test-basic", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-ecr-integ-test-basic/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-ecr-integ-test-basic/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-ecr-integ-test-basic/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-ecr-integ-test-basic/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-ecr-integ-test-basic/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.basic.ts b/packages/@aws-cdk/aws-ecr/test/integ.basic.ts index 2fc70610bf92c..94e5294cc6b50 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.basic.ts +++ b/packages/@aws-cdk/aws-ecr/test/integ.basic.ts @@ -1,4 +1,5 @@ import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as ecr from '../lib'; const app = new cdk.App(); @@ -11,4 +12,6 @@ new cdk.CfnOutput(stack, 'RepositoryURI', { value: repo.repositoryUri, }); -app.synth(); +new IntegTest(app, 'cdk-ecr-integ-test-basic', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/aws-ecr-integ-stack.assets.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/aws-ecr-integ-stack.assets.json index f35c9ed8f3ea7..fe0cefa7555ed 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/aws-ecr-integ-stack.assets.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/aws-ecr-integ-stack.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "0cdaf4a3ab8aceb7d41ed4fc691ab1db68e18ed76eb0764ab60a43b8f6ee1568": { "source": { diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdk.out b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets.json new file mode 100644 index 0000000000000..3394771e947f8 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.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/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.template.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.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/aws-ecr/test/integ.imagescan.js.snapshot/integ.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/integ.json index bd547f815075e..422932ae4b483 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.imagescan": { + "cdk-integ-ecr-image-scan/DefaultTest": { "stacks": [ "aws-ecr-integ-stack" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-ecr-image-scan/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/manifest.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/manifest.json index c905ad7b261d6..20fae323b5df8 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-ecr-integ-stack.assets": { "type": "cdk:asset-manifest", "properties": { @@ -71,6 +65,59 @@ ] }, "displayName": "aws-ecr-integ-stack" + }, + "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.template.json", + "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": [ + "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.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": [ + "cdkintegecrimagescanDefaultTestDeployAssert2E4CA4F5.assets" + ], + "metadata": { + "/cdk-integ-ecr-image-scan/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-ecr-image-scan/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-ecr-image-scan/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/tree.json b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/tree.json index b226ca289d7b7..cdb2820434a75 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-ecr-integ-stack": { "id": "aws-ecr-integ-stack", "path": "aws-ecr-integ-stack", @@ -88,20 +80,98 @@ "id": "RepositoryURI", "path": "aws-ecr-integ-stack/RepositoryURI", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-ecr-integ-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-ecr-integ-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-ecr-image-scan": { + "id": "cdk-integ-ecr-image-scan", + "path": "cdk-integ-ecr-image-scan", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-ecr-image-scan/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-ecr-image-scan/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-ecr-image-scan/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-ecr-image-scan/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-ecr-image-scan/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.ts b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.ts index 9feece9392f8e..4b0533b35cd03 100644 --- a/packages/@aws-cdk/aws-ecr/test/integ.imagescan.ts +++ b/packages/@aws-cdk/aws-ecr/test/integ.imagescan.ts @@ -1,4 +1,5 @@ import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as ecr from '../lib'; const app = new cdk.App(); @@ -15,4 +16,6 @@ new cdk.CfnOutput(stack, 'RepositoryURI', { value: repo.repositoryUri, }); -app.synth(); +new IntegTest(app, 'cdk-integ-ecr-image-scan', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts index 4eda8f884b813..6ca07346dff28 100644 --- a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts @@ -566,43 +566,15 @@ export class ContainerDefinition extends Construct { */ public addPortMappings(...portMappings: PortMapping[]) { this.portMappings.push(...portMappings.map(pm => { - if (this.taskDefinition.networkMode === NetworkMode.AWS_VPC || this.taskDefinition.networkMode === NetworkMode.HOST) { - if (pm.containerPort !== pm.hostPort && pm.hostPort !== undefined) { - throw new Error(`Host port (${pm.hostPort}) must be left out or equal to container port ${pm.containerPort} for network mode ${this.taskDefinition.networkMode}`); - } - } - // No empty strings as port mapping names. - if (pm.name === '') { - throw new Error('Port mapping name cannot be an empty string.'); - } - // Service connect logic. - if (pm.name || pm.appProtocol) { - - // Service connect only supports Awsvpc and Bridge network modes. - if (![NetworkMode.BRIDGE, NetworkMode.AWS_VPC].includes(this.taskDefinition.networkMode)) { - throw new Error(`Service connect related port mapping fields 'name' and 'appProtocol' are not supported for network mode ${this.taskDefinition.networkMode}`); - } - - // Name is not set but App Protocol is; this config is meaningless and we should throw. - if (!pm.name) { - throw new Error('Service connect-related port mapping field \'appProtocol\' cannot be set without \'name\''); - } - - if (this._namedPorts.has(pm.name)) { - throw new Error(`Port mapping name '${pm.name}' already exists on this container`); - } - this._namedPorts.set(pm.name, pm); + const portMap = new PortMap(this.taskDefinition.networkMode, pm); + portMap.validate(); + const serviceConnect = new ServiceConnect(this.taskDefinition.networkMode, pm); + if (serviceConnect.isServiceConnect()) { + serviceConnect.validate(); + this.setNamedPort(pm); } - - if (this.taskDefinition.networkMode === NetworkMode.BRIDGE) { - if (pm.hostPort === undefined) { - pm = { - ...pm, - hostPort: 0, - }; - } - } - return pm; + const sanitizedPM = this.addHostPortIfNeeded(pm); + return sanitizedPM; })); } @@ -688,6 +660,32 @@ export class ContainerDefinition extends Construct { return this._namedPorts.get(name); } + /** + * This method adds an namedPort + */ + private setNamedPort(pm: PortMapping) :void { + if (!pm.name) return; + if (this._namedPorts.has(pm.name)) { + throw new Error(`Port mapping name '${pm.name}' already exists on this container`); + } + this._namedPorts.set(pm.name, pm); + } + + + /** + * Set HostPort to 0 When netowork mode is Brdige + */ + private addHostPortIfNeeded(pm: PortMapping) :PortMapping { + const newPM = { + ...pm, + }; + if (this.taskDefinition.networkMode !== NetworkMode.BRIDGE) return newPM; + if (pm.hostPort !== undefined) return newPM; + newPM.hostPort = 0; + return newPM; + } + + /** * Whether this container definition references a specific JSON field of a secret * stored in Secrets Manager. @@ -1086,6 +1084,116 @@ export interface PortMapping { readonly appProtocol?: AppProtocol; } +/** + * PortMap ValueObjectClass having by ContainerDefinition + */ +export class PortMap { + + /** + * The networking mode to use for the containers in the task. + */ + readonly networkmode: NetworkMode; + + /** + * Port mappings allow containers to access ports on the host container instance to send or receive traffic. + */ + readonly portmapping: PortMapping; + + constructor(networkmode: NetworkMode, pm: PortMapping) { + this.networkmode = networkmode; + this.portmapping = pm; + } + + /** + * validate invalid portmapping and networkmode parameters. + * throw Error when invalid parameters. + */ + public validate(): void { + if (!this.isvalidPortName()) { + throw new Error('Port mapping name cannot be an empty string.'); + } + if (!this.isValidPorts()) { + const pm = this.portmapping; + throw new Error(`Host port (${pm.hostPort}) must be left out or equal to container port ${pm.containerPort} for network mode ${this.networkmode}`); + } + } + + private isvalidPortName(): boolean { + if (this.portmapping.name === '') { + return false; + } + return true; + } + + private isValidPorts() :boolean { + const isAwsVpcMode = this.networkmode == NetworkMode.AWS_VPC; + const isHostMode = this.networkmode == NetworkMode.HOST; + if (!isAwsVpcMode && !isHostMode) return true; + const hostPort = this.portmapping.hostPort; + const containerPort = this.portmapping.containerPort; + if (containerPort !== hostPort && hostPort !== undefined ) return false; + return true; + } + +} + + +/** + * ServiceConnect ValueObjectClass having by ContainerDefinition + */ +export class ServiceConnect { + /** + * Port mappings allow containers to access ports on the host container instance to send or receive traffic. + */ + readonly portmapping: PortMapping; + + /** + * The networking mode to use for the containers in the task. + */ + readonly networkmode: NetworkMode; + + constructor(networkmode: NetworkMode, pm: PortMapping) { + this.portmapping = pm; + this.networkmode = networkmode; + } + + /** + * Judge parameters can be serviceconnect logick. + * If parameters can be serviceConnect return true. + */ + public isServiceConnect() :boolean { + const hasPortname = this.portmapping.name; + const hasAppProtcol = this.portmapping.appProtocol; + if (hasPortname || hasAppProtcol) return true; + return false; + } + + /** + * Judge serviceconnect parametes are valid. + * If invalid, throw Error. + */ + public validate() :void { + if (!this.isValidNetworkmode()) { + throw new Error(`Service connect related port mapping fields 'name' and 'appProtocol' are not supported for network mode ${this.networkmode}`); + } + if (!this.isValidPortName()) { + throw new Error('Service connect-related port mapping field \'appProtocol\' cannot be set without \'name\''); + } + } + + private isValidNetworkmode() :boolean { + const isAwsVpcMode = this.networkmode == NetworkMode.AWS_VPC; + const isBridgeMode = this.networkmode == NetworkMode.BRIDGE; + if (isAwsVpcMode || isBridgeMode) return true; + return false; + } + + private isValidPortName() :boolean { + if (!this.portmapping.name) return false; + return true; + } +} + /** * Network protocol */ 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 df6b12e553769..12c8c699ff733 100644 --- a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts @@ -35,6 +35,156 @@ describe('container definition', () => { }); }); + describe('PortMap validates', () => { + test('throws when PortMapping.name is empty string.', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + name: '', + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const portMap = new ecs.PortMap(networkmode, portMapping); + // THEN + expect(() => { + portMap.validate(); + }).toThrow(); + }); + + describe('ContainerPort should not eqaul Hostport', () => { + test('when AWS_VPC Networkmode', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + hostPort: 8081, + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const portMap = new ecs.PortMap(networkmode, portMapping); + // THEN + expect(() => { + portMap.validate(); + }).toThrow(); + }); + + test('when Host Networkmode', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + hostPort: 8081, + }; + const networkmode = ecs.NetworkMode.HOST; + const portMap = new ecs.PortMap(networkmode, portMapping); + // THEN + expect(() => { + portMap.validate(); + }).toThrow(); + }); + }); + + describe('ContainerPort can equal HostPort cases', () => { + test('when Bridge Networkmode', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + hostPort: 8080, + }; + const networkmode = ecs.NetworkMode.BRIDGE; + const portMap = new ecs.PortMap(networkmode, portMapping); + // THEN + expect(() => { + portMap.validate(); + }).not.toThrow(); + }); + + }); + + }); + + describe('ServiceConnect class', () => { + describe('isServiceConnect', () => { + test('return true if params has portname', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + name: 'test', + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(serviceConnect.isServiceConnect()).toEqual(true); + }); + + test('return true if params has appProtocol', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + appProtocol: ecs.AppProtocol.http2, + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(serviceConnect.isServiceConnect()).toEqual(true); + }); + + test('return false if params has not appProtocl and portName ', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(serviceConnect.isServiceConnect()).toEqual(false); + }); + + }); + + describe('validate', () => { + test('throw if Host Networkmode', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + name: 'test', + }; + const networkmode = ecs.NetworkMode.HOST; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(() => { + serviceConnect.validate(); + }).toThrow(); + }); + + test('throw if has not portmap name', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + appProtocol: ecs.AppProtocol.http2, + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(() => { + serviceConnect.validate(); + }).toThrow('Service connect-related port mapping field \'appProtocol\' cannot be set without \'name\''); + }); + + test('should not throw if AWS_VPC NetworkMode and has portname', () => { + // GIVEN + const portMapping: ecs.PortMapping = { + containerPort: 8080, + name: 'test', + }; + const networkmode = ecs.NetworkMode.AWS_VPC; + const serviceConnect = new ecs.ServiceConnect(networkmode, portMapping); + // THEN + expect(() => { + serviceConnect.validate(); + }).not.toThrow(); + }); + + }); + + }); + test('port mapping throws an error when appProtocol is set without name', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-efs/lib/access-point.ts b/packages/@aws-cdk/aws-efs/lib/access-point.ts index 74eefa878773e..41424f96378e5 100644 --- a/packages/@aws-cdk/aws-efs/lib/access-point.ts +++ b/packages/@aws-cdk/aws-efs/lib/access-point.ts @@ -1,4 +1,4 @@ -import { ArnFormat, IResource, Resource, Stack } from '@aws-cdk/core'; +import { ArnFormat, IResource, Resource, Stack, Tags } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { IFileSystem } from './efs-file-system'; import { CfnAccessPoint } from './efs.generated'; @@ -218,6 +218,8 @@ export class AccessPoint extends AccessPointBase { } : undefined, }); + Tags.of(this).add('Name', this.node.path); + this.accessPointId = resource.ref; this.accessPointArn = Stack.of(scope).formatArn({ service: 'elasticfilesystem', diff --git a/packages/@aws-cdk/aws-efs/test/access-point.test.ts b/packages/@aws-cdk/aws-efs/test/access-point.test.ts index 488dbb93dee4f..6571be822a720 100644 --- a/packages/@aws-cdk/aws-efs/test/access-point.test.ts +++ b/packages/@aws-cdk/aws-efs/test/access-point.test.ts @@ -1,6 +1,6 @@ import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; -import { Stack } from '@aws-cdk/core'; +import { Stack, Tags } from '@aws-cdk/core'; import { AccessPoint, FileSystem } from '../lib'; let stack: Stack; @@ -31,6 +31,25 @@ test('new AccessPoint correctly', () => { Template.fromStack(stack).resourceCountIs('AWS::EFS::AccessPoint', 1); }); +test('support tags for AccessPoint', () => { + // WHEN + const accessPoint = new AccessPoint(stack, 'MyAccessPoint', { + fileSystem, + }); + Tags.of(accessPoint).add('key1', 'value1'); + Tags.of(accessPoint).add('key2', 'value2'); + Tags.of(accessPoint).add('Name', 'MyAccessPointName'); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::EFS::AccessPoint', { + AccessPointTags: [ + { Key: 'key1', Value: 'value1' }, + { Key: 'key2', Value: 'value2' }, + { Key: 'Name', Value: 'MyAccessPointName' }, + ], + }); +}); + test('import an AccessPoint using fromAccessPointId', () => { // WHEN const ap = new AccessPoint(stack, 'MyAccessPoint', { diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/FileSystemPolicyTestDefaultTestDeployAssertD0596FC1.assets.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/FileSystemPolicyTestDefaultTestDeployAssertD0596FC1.assets.json index 63310c336fab4..c89606077c44e 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/FileSystemPolicyTestDefaultTestDeployAssertD0596FC1.assets.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/FileSystemPolicyTestDefaultTestDeployAssertD0596FC1.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/cdk.out b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/integ.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/integ.json index 92343ca276aaf..a5b791d6df896 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "FileSystemPolicyTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/manifest.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/manifest.json index e59b3eec02264..3c673ba5033f3 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "test-efs-integ.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/c5e7b14cbe61beadd8ee29f1e2e8da7ac152bf472dfba586a792ff422a1eef41.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/7d5832d3a930b18cb36abc1ffaed24a2bf408a8130ba7fab108ff6f6fa75dd98.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -183,6 +183,12 @@ "data": "FileSystemEfsMountTarget24B8EBB43" } ], + "/test-efs-integ/AccessPoint/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AccessPointE936DE82" + } + ], "/test-efs-integ/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.assets.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.assets.json index 4b4483a20346e..2c398da3f69db 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.assets.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { - "c5e7b14cbe61beadd8ee29f1e2e8da7ac152bf472dfba586a792ff422a1eef41": { + "7d5832d3a930b18cb36abc1ffaed24a2bf408a8130ba7fab108ff6f6fa75dd98": { "source": { "path": "test-efs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c5e7b14cbe61beadd8ee29f1e2e8da7ac152bf472dfba586a792ff422a1eef41.json", + "objectKey": "7d5832d3a930b18cb36abc1ffaed24a2bf408a8130ba7fab108ff6f6fa75dd98.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.template.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.template.json index 7abbbf57f980e..0349d15da0f88 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.template.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/test-efs-integ.template.json @@ -464,6 +464,21 @@ "Ref": "VpcPrivateSubnet2Subnet3788AAA1" } } + }, + "AccessPointE936DE82": { + "Type": "AWS::EFS::AccessPoint", + "Properties": { + "FileSystemId": { + "Ref": "FileSystem8A8E25C0" + }, + "AccessPointTags": [ + { + "Key": "Name", + "Value": "MyAccessPoint" + } + ], + "RootDirectory": {} + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/tree.json b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/tree.json index d231356b874e9..b32beb54b1e25 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.js.snapshot/tree.json @@ -763,6 +763,39 @@ "version": "0.0.0" } }, + "AccessPoint": { + "id": "AccessPoint", + "path": "test-efs-integ/AccessPoint", + "children": { + "Resource": { + "id": "Resource", + "path": "test-efs-integ/AccessPoint/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EFS::AccessPoint", + "aws:cdk:cloudformation:props": { + "fileSystemId": { + "Ref": "FileSystem8A8E25C0" + }, + "accessPointTags": [ + { + "key": "Name", + "value": "MyAccessPoint" + } + ], + "rootDirectory": {} + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-efs.CfnAccessPoint", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-efs.AccessPoint", + "version": "0.0.0" + } + }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "test-efs-integ/BootstrapVersion", @@ -798,7 +831,7 @@ "path": "FileSystemPolicyTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.249" + "version": "10.1.252" } }, "DeployAssert": { @@ -844,7 +877,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.249" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.ts b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.ts index a468a6822e2f1..79f40dccec337 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.ts +++ b/packages/@aws-cdk/aws-efs/test/integ.efs-filesystem-policy.ts @@ -3,7 +3,7 @@ import { AccountRootPrincipal, PolicyDocument, PolicyStatement } from '@aws-cdk/ import * as cdk from '@aws-cdk/core'; // eslint-disable-next-line import/no-extraneous-dependencies import * as integ from '@aws-cdk/integ-tests'; -import { FileSystem } from '../lib'; +import { AccessPoint, FileSystem } from '../lib'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'test-efs-integ'); @@ -26,12 +26,17 @@ const myFileSystemPolicy = new PolicyDocument({ })], }); -new FileSystem(stack, 'FileSystem', { +const fileSystem = new FileSystem(stack, 'FileSystem', { vpc, fileSystemPolicy: myFileSystemPolicy, }); +const accessPoint = new AccessPoint(stack, 'AccessPoint', { + fileSystem, +}); +cdk.Tags.of(accessPoint).add('Name', 'MyAccessPoint'); + new integ.IntegTest(app, 'FileSystemPolicyTest', { testCases: [stack], }); -app.synth(); \ No newline at end of file +app.synth(); diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/cdk.out b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/integ.json b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/integ.json index 4d02881b45ff2..5092c4c2a994c 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ.efs": { "stacks": [ diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/manifest.json index a38f0441c01ba..e46186a23e262 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "test-efs-integ.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/5a176f99ace1339beed54ef48f307a4119e039540eec6e4f95196f9f2ce08b41.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bf1856ec9969cccf2ed5dcc40acf92ce4870f877b88f68aa2813b3feb3c775af.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -209,6 +203,12 @@ ] }, "displayName": "test-efs-integ" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json index 6b72588d8271c..f6e5a2cd9a4ed 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { - "5a176f99ace1339beed54ef48f307a4119e039540eec6e4f95196f9f2ce08b41": { + "bf1856ec9969cccf2ed5dcc40acf92ce4870f877b88f68aa2813b3feb3c775af": { "source": { "path": "test-efs-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "5a176f99ace1339beed54ef48f307a4119e039540eec6e4f95196f9f2ce08b41.json", + "objectKey": "bf1856ec9969cccf2ed5dcc40acf92ce4870f877b88f68aa2813b3feb3c775af.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json index 3db99e3c0979d..ca89c3654f94a 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/test-efs-integ.template.json @@ -435,6 +435,12 @@ "FileSystemId": { "Ref": "FileSystem8A8E25C0" }, + "AccessPointTags": [ + { + "Key": "Name", + "Value": "test-efs-integ/FileSystem/AccessPoint" + } + ], "PosixUser": { "Gid": "1000", "Uid": "1000" diff --git a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/tree.json b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/tree.json index 21c6134519363..ea1056800dbb4 100644 --- a/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-efs/test/integ.efs.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "test-efs-integ": { "id": "test-efs-integ", "path": "test-efs-integ", @@ -91,8 +83,8 @@ "id": "Acl", "path": "test-efs-integ/Vpc/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -258,8 +250,8 @@ "id": "Acl", "path": "test-efs-integ/Vpc/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -377,8 +369,8 @@ "id": "Acl", "path": "test-efs-integ/Vpc/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -496,8 +488,8 @@ "id": "Acl", "path": "test-efs-integ/Vpc/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -742,6 +734,12 @@ "fileSystemId": { "Ref": "FileSystem8A8E25C0" }, + "accessPointTags": [ + { + "key": "Name", + "value": "test-efs-integ/FileSystem/AccessPoint" + } + ], "posixUser": { "uid": "1000", "gid": "1000" @@ -772,17 +770,41 @@ "fqn": "@aws-cdk/aws-efs.FileSystem", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "test-efs-integ/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "test-efs-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/README.md b/packages/@aws-cdk/aws-eks/README.md index e10cba101ec14..4b146e1d50d9c 100644 --- a/packages/@aws-cdk/aws-eks/README.md +++ b/packages/@aws-cdk/aws-eks/README.md @@ -1193,6 +1193,20 @@ cluster.addHelmChart('ExternalSecretsOperator', { }); ``` +Helm chart can come with Custom Resource Definitions (CRDs) defined that by default will be installed by helm as well. However in special cases it might be needed to skip the installation of CRDs, for that the property `skipCrds` can be used. + +```ts +declare const cluster: eks.Cluster; +// option 1: use a construct +new eks.HelmChart(this, 'NginxIngress', { + cluster, + chart: 'nginx-ingress', + repository: 'https://helm.nginx.com/stable', + namespace: 'kube-system', + skipCrds: true, +}); +``` + ### OCI Charts OCI charts are also supported. diff --git a/packages/@aws-cdk/aws-eks/lib/helm-chart.ts b/packages/@aws-cdk/aws-eks/lib/helm-chart.ts index 9dfebd5ac0715..40e062ff157bd 100644 --- a/packages/@aws-cdk/aws-eks/lib/helm-chart.ts +++ b/packages/@aws-cdk/aws-eks/lib/helm-chart.ts @@ -78,6 +78,12 @@ export interface HelmChartOptions { * @default true */ readonly createNamespace?: boolean; + + /** + * if set, no CRDs will be installed + * @default - CRDs are installed if not already present + */ + readonly skipCrds?: boolean; } /** @@ -129,6 +135,8 @@ export class HelmChart extends Construct { const wait = props.wait ?? false; // default to create new namespace const createNamespace = props.createNamespace ?? true; + // default to not skip crd installation + const skipCrds = props.skipCrds ?? false; props.chartAsset?.grantRead(provider.handlerRole); @@ -148,6 +156,7 @@ export class HelmChart extends Construct { Namespace: props.namespace ?? 'default', Repository: props.repository, CreateNamespace: createNamespace || undefined, + SkipCrds: skipCrds || undefined, }, }); } 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 c9120c1926e03..34481f86a81d7 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 @@ -46,6 +46,7 @@ def helm_handler(event, context): create_namespace = props.get('CreateNamespace', None) repository = props.get('Repository', None) values_text = props.get('Values', None) + skip_crds = props.get('SkipCrds', False) # "log in" to the cluster subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', @@ -111,7 +112,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: @@ -146,7 +147,7 @@ def get_chart_from_oci(tmpdir, repository = None, version = None): raise Exception(f'Operation failed after {maxAttempts} attempts: {output}') -def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): +def helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None, skip_crds = False): import subprocess cmnd = ['helm', verb, release] @@ -166,6 +167,8 @@ def helm(verb, release, chart = None, repo = None, file = None, namespace = None cmnd.extend(['--namespace', namespace]) if wait: cmnd.append('--wait') + if skip_crds: + cmnd.append('--skip-crds') if not timeout is None: cmnd.extend(['--timeout', timeout]) cmnd.extend(['--kubeconfig', kubeconfig]) diff --git a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts index 93978ff1c1f1c..1c6236615dcd5 100644 --- a/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts +++ b/packages/@aws-cdk/aws-eks/lib/kubectl-provider.ts @@ -165,6 +165,11 @@ export class KubectlProvider extends NestedStack implements IKubectlProvider { iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'), ); + // For OCI helm chart public ECR authorization. + this.handlerRole.addManagedPolicy( + iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonElasticContainerRegistryPublicReadOnly'), + ); + // allow this handler to assume the kubectl role cluster.kubectlRole.grant(this.handlerRole, 'sts:AssumeRole'); diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index a42cda8ebb6a6..479e774d254a0 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -80,7 +80,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/lambda-layer-kubectl-v24": "^2.0.100", + "@aws-cdk/lambda-layer-kubectl-v24": "^2.0.113", "aws-cdk-lib": "2.47.0", "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", @@ -88,13 +88,13 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "@types/sinon": "^9.0.11", "@types/yaml": "1.9.6", - "aws-sdk": "^2.1317.0", - "cdk8s": "^2.7.2", - "cdk8s-plus-24": "2.4.23", + "aws-sdk": "^2.1325.0", + "cdk8s": "^2.7.15", + "cdk8s-plus-24": "2.4.40", "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 6dc7ebac05d97..92e010a8ac378 100644 --- a/packages/@aws-cdk/aws-eks/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-eks/test/cluster.test.ts @@ -2103,6 +2103,13 @@ describe('cluster', () => { ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', ]], }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly', + ]], + }, ], }); }); @@ -2297,6 +2304,13 @@ describe('cluster', () => { ':iam::aws:policy/AmazonEC2ContainerRegistryReadOnly', ]], }, + { + 'Fn::Join': ['', [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly', + ]], + }, ], }); }); diff --git a/packages/@aws-cdk/aws-eks/test/helm-chart.test.ts b/packages/@aws-cdk/aws-eks/test/helm-chart.test.ts index 6da8b851174eb..3587d4071bb2d 100644 --- a/packages/@aws-cdk/aws-eks/test/helm-chart.test.ts +++ b/packages/@aws-cdk/aws-eks/test/helm-chart.test.ts @@ -226,5 +226,27 @@ describe('helm chart', () => { // THEN Template.fromStack(stack).hasResourceProperties(eks.HelmChart.RESOURCE_TYPE, { Timeout: '600s' }); }); + + test('should disable skip crds by default', () => { + // GIVEN + const { stack, cluster } = testFixtureCluster(); + + // WHEN + new eks.HelmChart(stack, 'MyChart', { cluster, chart: 'chart' }); + + // THEN + const charts = Template.fromStack(stack).findResources(eks.HelmChart.RESOURCE_TYPE, { SkipCrds: false }); + expect(Object.keys(charts).length).toEqual(0); + }); + test('should enable atomic operations when specified', () => { + // GIVEN + const { stack, cluster } = testFixtureCluster(); + + // WHEN + new eks.HelmChart(stack, 'MyAtomicChart', { cluster, chart: 'chart', skipCrds: true }); + + // THEN + Template.fromStack(stack).hasResourceProperties(eks.HelmChart.RESOURCE_TYPE, { SkipCrds: true }); + }); }); }); diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 71% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index a4c5ba868774f..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQ2hHLENBQUM7SUFoQkQsSUFBVyxXQUFXO1FBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUU7WUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO1NBQy9FO1FBRUQsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUM7SUFDakMsQ0FBQztJQVlELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsMENBQTBDLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtZQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7U0FDMUM7UUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFD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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztTQUN0RTtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2FBQ3ZCLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7Z0JBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7YUFDeEM7WUFBQSxDQUFDO1lBQ0YsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUN4Qiw4RkFBOEY7Z0JBQzlGLHFHQUFxRztnQkFDckcsaUVBQWlFO2dCQUNqRSxNQUFNLENBQUMsa0JBQWtCLEdBQUc7b0JBQzFCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMscUJBQXFCO29CQUM3RSxvQkFBb0IsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQjtvQkFDM0UsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBaUI7aUJBQ3RFLENBQUM7YUFDSDtZQUNELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUVsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7U0FDbkQ7UUFFRCxhQUFhO1FBQ2IsT0FBTztLQUNSO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEMsb0VBQW9FO1FBQ3BFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDMUIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNiLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7YUFDOUI7WUFFRCx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLHFFQUFxRTtTQUN0RTtRQUVELE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ3hCO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUFDLFVBQWtCO1FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFFekQsNEVBQTRFO1FBQzVFLHdCQUF3QjtRQUN4QixNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDckYsSUFBSSxPQUFPLEVBQUUsT0FBTyxLQUFLLFVBQVUsRUFBRTtZQUNuQyxPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixPQUFPLENBQUMsT0FBTywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3RGLE9BQU87U0FDUjtRQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzVHLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUNuRDtJQUVPLEtBQUssQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUU3Qiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLHNEQUFzRDtRQUN0RCxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ2hDLDZFQUE2RTtZQUM3RSxpQkFBaUI7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1NBQ2xEO2FBQU0sSUFBSSxPQUFPLEVBQUUsTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUN2QyxPQUFPO2dCQUNMLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUM7U0FDSDthQUFNO1lBQ0wsT0FBTztnQkFDTCxVQUFVLEVBQUUsSUFBSTtnQkFDaEIsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUMxQixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBRWhCLG9FQUFvRTtvQkFDcEUsOERBQThEO29CQUM5RCxrRUFBa0U7b0JBQ2xFLGFBQWE7b0JBRWIsd0JBQXdCLEVBQUUsT0FBTyxDQUFDLG9CQUFvQixFQUFFLElBQUksSUFBSSxFQUFFO29CQUNsRSxzQkFBc0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCLEVBQUUsc0JBQXNCLElBQUksRUFBRTtvQkFDaEYsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxJQUFJLEVBQUU7b0JBQzVELG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtvQkFFdkUsNEdBQTRHO29CQUM1Ryw4SEFBOEg7b0JBQzlILHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLEVBQUU7aUJBQ2xGO2FBQ0YsQ0FBQztTQUNIO0tBQ0Y7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQUMsV0FBbUI7UUFDbkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFL0MsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsV0FBVztZQUN0QixRQUFRLEVBQUUsV0FBVztTQUN0QixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUU7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUN2RTtRQUVELFFBQVEsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUM1QyxLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxLQUFLLENBQUM7WUFDZixLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxJQUFJLENBQUM7WUFDZCxLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssV0FBVztnQkFDZCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixXQUFXLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEk7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDOUc7S0FDRjtJQUVPLG1CQUFtQjtRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXO1FBQzVELE1BQU0sTUFBTSxHQUFHLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsT0FBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztLQUM5QjtDQUNGO0FBM1FELHdEQTJRQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQVU7SUFFNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFbkMsMEhBQTBIO0lBQzFILDhIQUE4SDtJQUU5SCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDMUUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsS0FBSyxNQUFNLENBQUM7S0FDOUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsb0JBQW9CLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDekUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsS0FBSyxNQUFNLENBQUM7S0FDNUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDbkUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxNQUFNLENBQUM7S0FDaEc7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUVoQixDQUFDO0FBYUQsU0FBUyxhQUFhLENBQUMsUUFBK0MsRUFBRSxRQUFzQztJQUM1RyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXJELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxFQUFFLENBQUM7SUFDdEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUV0RCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsZ0JBQWdCLElBQUksRUFBRSxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFFL0MsT0FBTztRQUNMLFdBQVcsRUFBRSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJO1FBQzVDLFVBQVUsRUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDL0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUMvRyxZQUFZLEVBQ1YsV0FBVyxDQUFDLHFCQUFxQixLQUFLLFdBQVcsQ0FBQyxxQkFBcUI7WUFDdkUsV0FBVyxDQUFDLG9CQUFvQixLQUFLLFdBQVcsQ0FBQyxvQkFBb0I7WUFDckUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsb0JBQW9CLENBQUM7UUFDeEQsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDbEQsYUFBYSxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDcEQsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js deleted file mode 100644 index a5480014d5fc4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js +++ /dev/null @@ -1,43 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ResourceHandler = void 0; -class ResourceHandler { - constructor(eks, event) { - this.eks = eks; - this.requestType = event.RequestType; - this.requestId = event.RequestId; - this.logicalResourceId = event.LogicalResourceId; - this.physicalResourceId = event.PhysicalResourceId; - this.event = event; - const roleToAssume = event.ResourceProperties.AssumeRoleArn; - if (!roleToAssume) { - throw new Error('AssumeRoleArn must be provided'); - } - eks.configureAssumeRole({ - RoleArn: roleToAssume, - RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, - }); - } - onEvent() { - switch (this.requestType) { - case 'Create': return this.onCreate(); - case 'Update': return this.onUpdate(); - case 'Delete': return this.onDelete(); - } - throw new Error(`Invalid request type ${this.requestType}`); - } - isComplete() { - switch (this.requestType) { - case 'Create': return this.isCreateComplete(); - case 'Update': return this.isUpdateComplete(); - case 'Delete': return this.isDeleteComplete(); - } - throw new Error(`Invalid request type ${this.requestType}`); - } - log(x) { - // eslint-disable-next-line no-console - console.log(JSON.stringify(x, undefined, 2)); - } -} -exports.ResourceHandler = ResourceHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29tbW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSxNQUFzQixlQUFlO0lBT25DLFlBQStCLEdBQWMsRUFBRSxLQUFvQjtRQUFwQyxRQUFHLEdBQUgsR0FBRyxDQUFXO1FBQzNDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNyQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUNqRCxJQUFJLENBQUMsa0JBQWtCLEdBQUksS0FBYSxDQUFDLGtCQUFrQixDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxHQUFHLENBQUMsbUJBQW1CLENBQUM7WUFDdEIsT0FBTyxFQUFFLFlBQVk7WUFDckIsZUFBZSxFQUFFLHFCQUFxQixJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7U0FDM0UsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLE9BQU87UUFDWixRQUFRLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDeEIsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3RDLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDdkM7UUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRU0sVUFBVTtRQUNmLFFBQVEsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUN4QixLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDOUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzlDLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztTQUMvQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFUyxHQUFHLENBQUMsQ0FBTTtRQUNsQixzQ0FBc0M7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvQyxDQUFDO0NBUUY7QUF4REQsMENBd0RDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWtzVXBkYXRlSWQge1xuICAvKipcbiAgICogSWYgdGhpcyBmaWVsZCBpcyBpbmNsdWRlZCBpbiBhbiBldmVudCBwYXNzZWQgdG8gXCJJc0NvbXBsZXRlXCIsIGl0IG1lYW5zIHdlXG4gICAqIGluaXRpYXRlZCBhbiBFS1MgdXBkYXRlIHRoYXQgc2hvdWxkIGJlIG1vbml0b3JlZCB1c2luZyBla3M6RGVzY3JpYmVVcGRhdGVcbiAgICogaW5zdGVhZCBvZiBqdXN0IGxvb2tpbmcgYXQgdGhlIGNsdXN0ZXIgc3RhdHVzLlxuICAgKi9cbiAgRWtzVXBkYXRlSWQ/OiBzdHJpbmdcbn1cblxuZXhwb3J0IHR5cGUgUmVzb3VyY2VFdmVudCA9IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiBFa3NVcGRhdGVJZDtcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlc291cmNlSGFuZGxlciB7XG4gIHByb3RlY3RlZCByZWFkb25seSByZXF1ZXN0SWQ6IHN0cmluZztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZ2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSByZXF1ZXN0VHlwZTogJ0NyZWF0ZScgfCAnVXBkYXRlJyB8ICdEZWxldGUnO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXZlbnQ6IFJlc291cmNlRXZlbnQ7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHJlYWRvbmx5IGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHRoaXMucmVxdWVzdFR5cGUgPSBldmVudC5SZXF1ZXN0VHlwZTtcbiAgICB0aGlzLnJlcXVlc3RJZCA9IGV2ZW50LlJlcXVlc3RJZDtcbiAgICB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkID0gZXZlbnQuTG9naWNhbFJlc291cmNlSWQ7XG4gICAgdGhpcy5waHlzaWNhbFJlc291cmNlSWQgPSAoZXZlbnQgYXMgYW55KS5QaHlzaWNhbFJlc291cmNlSWQ7XG4gICAgdGhpcy5ldmVudCA9IGV2ZW50O1xuXG4gICAgY29uc3Qgcm9sZVRvQXNzdW1lID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkFzc3VtZVJvbGVBcm47XG4gICAgaWYgKCFyb2xlVG9Bc3N1bWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXNzdW1lUm9sZUFybiBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gICAgfVxuXG4gICAgZWtzLmNvbmZpZ3VyZUFzc3VtZVJvbGUoe1xuICAgICAgUm9sZUFybjogcm9sZVRvQXNzdW1lLFxuICAgICAgUm9sZVNlc3Npb25OYW1lOiBgQVdTQ0RLLkVLU0NsdXN0ZXIuJHt0aGlzLnJlcXVlc3RUeXBlfS4ke3RoaXMucmVxdWVzdElkfWAsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgb25FdmVudCgpIHtcbiAgICBzd2l0Y2ggKHRoaXMucmVxdWVzdFR5cGUpIHtcbiAgICAgIGNhc2UgJ0NyZWF0ZSc6IHJldHVybiB0aGlzLm9uQ3JlYXRlKCk7XG4gICAgICBjYXNlICdVcGRhdGUnOiByZXR1cm4gdGhpcy5vblVwZGF0ZSgpO1xuICAgICAgY2FzZSAnRGVsZXRlJzogcmV0dXJuIHRoaXMub25EZWxldGUoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVxdWVzdCB0eXBlICR7dGhpcy5yZXF1ZXN0VHlwZX1gKTtcbiAgfVxuXG4gIHB1YmxpYyBpc0NvbXBsZXRlKCkge1xuICAgIHN3aXRjaCAodGhpcy5yZXF1ZXN0VHlwZSkge1xuICAgICAgY2FzZSAnQ3JlYXRlJzogcmV0dXJuIHRoaXMuaXNDcmVhdGVDb21wbGV0ZSgpO1xuICAgICAgY2FzZSAnVXBkYXRlJzogcmV0dXJuIHRoaXMuaXNVcGRhdGVDb21wbGV0ZSgpO1xuICAgICAgY2FzZSAnRGVsZXRlJzogcmV0dXJuIHRoaXMuaXNEZWxldGVDb21wbGV0ZSgpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByZXF1ZXN0IHR5cGUgJHt0aGlzLnJlcXVlc3RUeXBlfWApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGxvZyh4OiBhbnkpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHgsIHVuZGVmaW5lZCwgMikpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIG9uRGVsZXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlIHwgdm9pZD47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvblVwZGF0ZSgpOiBQcm9taXNlPChPbkV2ZW50UmVzcG9uc2UgJiBFa3NVcGRhdGVJZCkgfCB2b2lkPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIGlzQ3JlYXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgaXNEZWxldGVDb21wbGV0ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBpc1VwZGF0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFa3NDbGllbnQge1xuICBjb25maWd1cmVBc3N1bWVSb2xlKHJlcXVlc3Q6IGF3cy5TVFMuQXNzdW1lUm9sZVJlcXVlc3QpOiB2b2lkO1xuICBjcmVhdGVDbHVzdGVyKHJlcXVlc3Q6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlc3BvbnNlPjtcbiAgZGVsZXRlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkRlbGV0ZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlbGV0ZUNsdXN0ZXJSZXNwb25zZT47XG4gIGRlc2NyaWJlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkRlc2NyaWJlQ2x1c3RlclJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVDbHVzdGVyUmVzcG9uc2U+O1xuICB1cGRhdGVDbHVzdGVyQ29uZmlnKHJlcXVlc3Q6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1Jlc3BvbnNlPjtcbiAgdXBkYXRlQ2x1c3RlclZlcnNpb24ocmVxdWVzdDogYXdzLkVLUy5VcGRhdGVDbHVzdGVyVmVyc2lvblJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuVXBkYXRlQ2x1c3RlclZlcnNpb25SZXNwb25zZT47XG4gIGRlc2NyaWJlVXBkYXRlKHJlcTogYXdzLkVLUy5EZXNjcmliZVVwZGF0ZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVVcGRhdGVSZXNwb25zZT47XG4gIGNyZWF0ZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuQ3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2U+O1xuICBkZXNjcmliZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuRGVzY3JpYmVGYXJnYXRlUHJvZmlsZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVzY3JpYmVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlPjtcbiAgZGVsZXRlRmFyZ2F0ZVByb2ZpbGUocmVxdWVzdDogYXdzLkVLUy5EZWxldGVGYXJnYXRlUHJvZmlsZVJlcXVlc3QpOiBQcm9taXNlPGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZT47XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js deleted file mode 100644 index 91815a754a525..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js +++ /dev/null @@ -1,102 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.FargateProfileResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_NAME_LEN = 63; -class FargateProfileResourceHandler extends common_1.ResourceHandler { - async onCreate() { - const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); - const createFargateProfile = { - fargateProfileName, - ...this.event.ResourceProperties.Config, - }; - this.log({ createFargateProfile }); - const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); - this.log({ createFargateProfileResponse }); - if (!createFargateProfileResponse.fargateProfile) { - throw new Error('invalid CreateFargateProfile response'); - } - return { - PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, - Data: { - fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, - }, - }; - } - async onDelete() { - if (!this.physicalResourceId) { - throw new Error('Cannot delete a profile without a physical id'); - } - const deleteFargateProfile = { - clusterName: this.event.ResourceProperties.Config.clusterName, - fargateProfileName: this.physicalResourceId, - }; - this.log({ deleteFargateProfile }); - const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); - this.log({ deleteFargateProfileResponse }); - return; - } - async onUpdate() { - // all updates require a replacement. as long as name is generated, we are - // good. if name is explicit, update will fail, which is common when trying - // to replace cfn resources with explicit physical names - return this.onCreate(); - } - async isCreateComplete() { - return this.isUpdateComplete(); - } - async isUpdateComplete() { - const status = await this.queryStatus(); - return { - IsComplete: status === 'ACTIVE', - }; - } - async isDeleteComplete() { - const status = await this.queryStatus(); - return { - IsComplete: status === 'NOT_FOUND', - }; - } - /** - * Generates a fargate profile name. - */ - generateProfileName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } - /** - * Queries the Fargate profile's current status and returns the status or - * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). - */ - async queryStatus() { - if (!this.physicalResourceId) { - throw new Error('Unable to determine status for fargate profile without a resource name'); - } - const describeFargateProfile = { - clusterName: this.event.ResourceProperties.Config.clusterName, - fargateProfileName: this.physicalResourceId, - }; - try { - this.log({ describeFargateProfile }); - const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); - this.log({ describeFargateProfileResponse }); - const status = describeFargateProfileResponse.fargateProfile?.status; - if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { - throw new Error(status); - } - return status; - } - catch (describeFargateProfileError) { - if (describeFargateProfileError.code === 'ResourceNotFoundException') { - this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); - return 'NOT_FOUND'; - } - this.log({ describeFargateProfileError }); - throw describeFargateProfileError; - } - } -} -exports.FargateProfileResourceHandler = FargateProfileResourceHandler; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZhcmdhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUNBQTJDO0FBRTNDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUV4QixNQUFhLDZCQUE4QixTQUFRLHdCQUFlO0lBQ3RELEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFakgsTUFBTSxvQkFBb0IsR0FBd0M7WUFDaEUsa0JBQWtCO1lBQ2xCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNO1NBQ3hDLENBQUM7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sNEJBQTRCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsY0FBYyxFQUFFO1lBQ2hELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUMxRDtRQUVELE9BQU87WUFDTCxrQkFBa0IsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsa0JBQWtCO1lBQ2xGLElBQUksRUFBRTtnQkFDSixpQkFBaUIsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsaUJBQWlCO2FBQ2pGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFUyxLQUFLLENBQUMsUUFBUTtRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQztTQUNsRTtRQUVELE1BQU0sb0JBQW9CLEdBQXdDO1lBQ2hFLFdBQVcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxXQUFXO1lBQzdELGtCQUFrQixFQUFFLElBQUksQ0FBQyxrQkFBa0I7U0FDNUMsQ0FBQztRQUVGLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxvQkFBb0IsRUFBRSxDQUFDLENBQUM7UUFDbkMsTUFBTSw0QkFBNEIsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUMvRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDO1FBRTNDLE9BQU87SUFDVCxDQUFDO0lBRVMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsMEVBQTBFO1FBQzFFLDJFQUEyRTtRQUMzRSx3REFBd0Q7UUFDeEQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QyxPQUFPO1lBQ0wsVUFBVSxFQUFFLE1BQU0sS0FBSyxRQUFRO1NBQ2hDLENBQUM7SUFDSixDQUFDO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QyxPQUFPO1lBQ0wsVUFBVSxFQUFFLE1BQU0sS0FBSyxXQUFXO1NBQ25DLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSyxtQkFBbUI7UUFDekIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVztRQUM1RCxNQUFNLE1BQU0sR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDaEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxPQUFPLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsV0FBVztRQUN2QixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsd0VBQXdFLENBQUMsQ0FBQztTQUMzRjtRQUVELE1BQU0sc0JBQXNCLEdBQTBDO1lBQ3BFLFdBQVcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxXQUFXO1lBQzdELGtCQUFrQixFQUFFLElBQUksQ0FBQyxrQkFBa0I7U0FDNUMsQ0FBQztRQUVGLElBQUk7WUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sOEJBQThCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLHNCQUFzQixDQUFDLHNCQUFzQixDQUFDLENBQUM7WUFDckcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDhCQUE4QixFQUFFLENBQUMsQ0FBQztZQUM3QyxNQUFNLE1BQU0sR0FBRyw4QkFBOEIsQ0FBQyxjQUFjLEVBQUUsTUFBTSxDQUFDO1lBRXJFLElBQUksTUFBTSxLQUFLLGVBQWUsSUFBSSxNQUFNLEtBQUssZUFBZSxFQUFFO2dCQUM1RCxNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO2FBQ3pCO1lBRUQsT0FBTyxNQUFNLENBQUM7U0FDZjtRQUFDLE9BQU8sMkJBQTJCLEVBQUU7WUFDcEMsSUFBSSwyQkFBMkIsQ0FBQyxJQUFJLEtBQUssMkJBQTJCLEVBQUU7Z0JBQ3BFLElBQUksQ0FBQyxHQUFHLENBQUMsZ0dBQWdHLENBQUMsQ0FBQztnQkFDM0csT0FBTyxXQUFXLENBQUM7YUFDcEI7WUFFRCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsMkJBQTJCLEVBQUUsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sMkJBQTJCLENBQUM7U0FDbkM7SUFDSCxDQUFDO0NBQ0Y7QUFqSEQsc0VBaUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgUmVzb3VyY2VIYW5kbGVyIH0gZnJvbSAnLi9jb21tb24nO1xuXG5jb25zdCBNQVhfTkFNRV9MRU4gPSA2MztcblxuZXhwb3J0IGNsYXNzIEZhcmdhdGVQcm9maWxlUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCkge1xuICAgIGNvbnN0IGZhcmdhdGVQcm9maWxlTmFtZSA9IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5mYXJnYXRlUHJvZmlsZU5hbWUgPz8gdGhpcy5nZW5lcmF0ZVByb2ZpbGVOYW1lKCk7XG5cbiAgICBjb25zdCBjcmVhdGVGYXJnYXRlUHJvZmlsZTogYXdzLkVLUy5DcmVhdGVGYXJnYXRlUHJvZmlsZVJlcXVlc3QgPSB7XG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWUsXG4gICAgICAuLi50aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcsXG4gICAgfTtcblxuICAgIHRoaXMubG9nKHsgY3JlYXRlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgY29uc3QgY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUZhcmdhdGVQcm9maWxlKGNyZWF0ZUZhcmdhdGVQcm9maWxlKTtcbiAgICB0aGlzLmxvZyh7IGNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG5cbiAgICBpZiAoIWNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBDcmVhdGVGYXJnYXRlUHJvZmlsZSByZXNwb25zZScpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGNyZWF0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGUuZmFyZ2F0ZVByb2ZpbGVOYW1lLFxuICAgICAgRGF0YToge1xuICAgICAgICBmYXJnYXRlUHJvZmlsZUFybjogY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZS5mYXJnYXRlUHJvZmlsZUFybixcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZWxldGUgYSBwcm9maWxlIHdpdGhvdXQgYSBwaHlzaWNhbCBpZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGV0ZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkRlbGV0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGNsdXN0ZXJOYW1lOiB0aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcuY2x1c3Rlck5hbWUsXG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWU6IHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIH07XG5cbiAgICB0aGlzLmxvZyh7IGRlbGV0ZUZhcmdhdGVQcm9maWxlIH0pO1xuICAgIGNvbnN0IGRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZWxldGVGYXJnYXRlUHJvZmlsZShkZWxldGVGYXJnYXRlUHJvZmlsZSk7XG4gICAgdGhpcy5sb2coeyBkZWxldGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlIH0pO1xuXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uVXBkYXRlKCkge1xuICAgIC8vIGFsbCB1cGRhdGVzIHJlcXVpcmUgYSByZXBsYWNlbWVudC4gYXMgbG9uZyBhcyBuYW1lIGlzIGdlbmVyYXRlZCwgd2UgYXJlXG4gICAgLy8gZ29vZC4gaWYgbmFtZSBpcyBleHBsaWNpdCwgdXBkYXRlIHdpbGwgZmFpbCwgd2hpY2ggaXMgY29tbW9uIHdoZW4gdHJ5aW5nXG4gICAgLy8gdG8gcmVwbGFjZSBjZm4gcmVzb3VyY2VzIHdpdGggZXhwbGljaXQgcGh5c2ljYWwgbmFtZXNcbiAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzQ3JlYXRlQ29tcGxldGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNVcGRhdGVDb21wbGV0ZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgdGhpcy5xdWVyeVN0YXR1cygpO1xuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBzdGF0dXMgPT09ICdBQ1RJVkUnLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNEZWxldGVDb21wbGV0ZSgpIHtcbiAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnF1ZXJ5U3RhdHVzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IHN0YXR1cyA9PT0gJ05PVF9GT1VORCcsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBmYXJnYXRlIHByb2ZpbGUgbmFtZS5cbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVQcm9maWxlTmFtZSgpIHtcbiAgICBjb25zdCBzdWZmaXggPSB0aGlzLnJlcXVlc3RJZC5yZXBsYWNlKC8tL2csICcnKTsgLy8gMzIgY2hhcnNcbiAgICBjb25zdCBvZmZzZXQgPSBNQVhfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJpZXMgdGhlIEZhcmdhdGUgcHJvZmlsZSdzIGN1cnJlbnQgc3RhdHVzIGFuZCByZXR1cm5zIHRoZSBzdGF0dXMgb3JcbiAgICogTk9UX0ZPVU5EIGlmIHRoZSBwcm9maWxlIGRvZXNuJ3QgZXhpc3QgKGkuZS4gaXQgaGFzIGJlZW4gZGVsZXRlZCkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHF1ZXJ5U3RhdHVzKCk6IFByb21pc2U8YXdzLkVLUy5GYXJnYXRlUHJvZmlsZVN0YXR1cyB8ICdOT1RfRk9VTkQnIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmFibGUgdG8gZGV0ZXJtaW5lIHN0YXR1cyBmb3IgZmFyZ2F0ZSBwcm9maWxlIHdpdGhvdXQgYSByZXNvdXJjZSBuYW1lJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZTogYXdzLkVLUy5EZXNjcmliZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGNsdXN0ZXJOYW1lOiB0aGlzLmV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Db25maWcuY2x1c3Rlck5hbWUsXG4gICAgICBmYXJnYXRlUHJvZmlsZU5hbWU6IHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIH07XG5cbiAgICB0cnkge1xuXG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgICBjb25zdCBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZUZhcmdhdGVQcm9maWxlKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUpO1xuICAgICAgdGhpcy5sb2coeyBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG4gICAgICBjb25zdCBzdGF0dXMgPSBkZXNjcmliZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UuZmFyZ2F0ZVByb2ZpbGU/LnN0YXR1cztcblxuICAgICAgaWYgKHN0YXR1cyA9PT0gJ0NSRUFURV9GQUlMRUQnIHx8IHN0YXR1cyA9PT0gJ0RFTEVURV9GQUlMRUQnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihzdGF0dXMpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3RhdHVzO1xuICAgIH0gY2F0Y2ggKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvcikge1xuICAgICAgaWYgKGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvci5jb2RlID09PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhpcy5sb2coJ3JlY2VpdmVkIFJlc291cmNlTm90Rm91bmRFeGNlcHRpb24sIHRoaXMgbWVhbnMgdGhlIHByb2ZpbGUgaGFzIGJlZW4gZGVsZXRlZCAob3IgbmV2ZXIgZXhpc3RlZCknKTtcbiAgICAgICAgcmV0dXJuICdOT1RfRk9VTkQnO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvciB9KTtcbiAgICAgIHRocm93IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVFcnJvcjtcbiAgICB9XG4gIH1cbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json index 7ab4fbe9c8163..74a70481a208c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,15 +27,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -53,15 +53,15 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -118,7 +118,7 @@ } } }, - "6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa": { + "e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd": { "source": { "path": "awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json", + "objectKey": "e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe": { + "b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05": { "source": { "path": "awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json", "packaging": "file" @@ -139,12 +139,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json", + "objectKey": "b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8": { + "d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f": { "source": { "path": "aws-cdk-eks-cluster-alb-controller-test.template.json", "packaging": "file" @@ -152,7 +152,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8.json", + "objectKey": "d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json index eec2a808fa721..8076bfb7d4689 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/aws-cdk-eks-cluster-alb-controller-test.template.json @@ -983,7 +983,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json" + "/e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json" ] ] }, @@ -1018,7 +1018,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json" + "/b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json index 49d2f81af953f..534e2cac21573 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkclusteralbcontrollerDefaultTestDeployAssert78AE94CA.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json index 97c528c79331d..b22efad346b63 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksClusterResourceProvider5DBBAFBB.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json index e6d825f2a3324..70d390d2737c9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/awscdkeksclusteralbcontrollertestawscdkawseksKubectlProviderA1AC28D1.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json index 77a12a9e47232..e4e3b445b834c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-cluster-alb-controller/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json index 905c34e872fc0..44b356cc9a4e8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-alb-controller-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/238b406e7ada5a7a0848309eef25cca04f52ecca98b545b9c67196669131e8c8.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/d9fceb38127eccde41bf131a9109819a47a96e69777046c86417c8f4d36f8b2f.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json index 7dd81a6f1f937..d49f7060509a5 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.alb-controller.js.snapshot/tree.json @@ -1511,7 +1511,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1684,7 +1684,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2582,7 +2582,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6df565359d56c0de1e282f3c7873eb1a3f559e7c211404cd093371d2353fafaa.json" + "/e4ab354e4ce56910344523e060e9ee973ebdfc30595080f5c68466ef4864e7cd.json" ] ] }, @@ -2681,6 +2681,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2780,7 +2792,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3202,7 +3214,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/e3798b4ae5b4db51a5a5aefe3810d3e8a7d38f80580164d4e420662c13779fbe.json" + "/b36b8f77c87ea19316f26c348678df34ab1ae50aafc1fe31ed45171c2c04ab05.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['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) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztTQUN0RTtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2FBQ3ZCLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7Z0JBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7YUFDeEM7WUFBQSxDQUFDO1lBQ0YsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUN4Qiw4RkFBOEY7Z0JBQzlGLHFHQUFxRztnQkFDckcsaUVBQWlFO2dCQUNqRSxNQUFNLENBQUMsa0JBQWtCLEdBQUc7b0JBQzFCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMscUJBQXFCO29CQUM3RSxvQkFBb0IsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQjtvQkFDM0UsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBaUI7aUJBQ3RFLENBQUM7YUFDSDtZQUNELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUVsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7U0FDbkQ7UUFFRCxhQUFhO1FBQ2IsT0FBTztLQUNSO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEMsb0VBQW9FO1FBQ3BFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDMUIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNiLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7YUFDOUI7WUFFRCx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLHFFQUFxRTtTQUN0RTtRQUVELE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ3hCO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUFDLFVBQWtCO1FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFFekQsNEVBQTRFO1FBQzVFLHdCQUF3QjtRQUN4QixNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDckYsSUFBSSxPQUFPLEVBQUUsT0FBTyxLQUFLLFVBQVUsRUFBRTtZQUNuQyxPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixPQUFPLENBQUMsT0FBTywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3RGLE9BQU87U0FDUjtRQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzVHLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUNuRDtJQUVPLEtBQUssQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUU3Qiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLHNEQUFzRDtRQUN0RCxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ2hDLDZFQUE2RTtZQUM3RSxpQkFBaUI7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1NBQ2xEO2FBQU0sSUFBSSxPQUFPLEVBQUUsTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUN2QyxPQUFPO2dCQUNMLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUM7U0FDSDthQUFNO1lBQ0wsT0FBTztnQkFDTCxVQUFVLEVBQUUsSUFBSTtnQkFDaEIsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUMxQixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBRWhCLG9FQUFvRTtvQkFDcEUsOERBQThEO29CQUM5RCxrRUFBa0U7b0JBQ2xFLGFBQWE7b0JBRWIsd0JBQXdCLEVBQUUsT0FBTyxDQUFDLG9CQUFvQixFQUFFLElBQUksSUFBSSxFQUFFO29CQUNsRSxzQkFBc0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCLEVBQUUsc0JBQXNCLElBQUksRUFBRTtvQkFDaEYsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxJQUFJLEVBQUU7b0JBQzVELG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtvQkFFdkUsNEdBQTRHO29CQUM1Ryw4SEFBOEg7b0JBQzlILHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLEVBQUU7aUJBQ2xGO2FBQ0YsQ0FBQztTQUNIO0tBQ0Y7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQUMsV0FBbUI7UUFDbkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFL0MsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsV0FBVztZQUN0QixRQUFRLEVBQUUsV0FBVztTQUN0QixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUU7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUN2RTtRQUVELFFBQVEsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUM1QyxLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxLQUFLLENBQUM7WUFDZixLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxJQUFJLENBQUM7WUFDZCxLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssV0FBVztnQkFDZCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixXQUFXLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEk7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDOUc7S0FDRjtJQUVPLG1CQUFtQjtRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXO1FBQzVELE1BQU0sTUFBTSxHQUFHLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsT0FBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztLQUM5QjtDQUNGO0FBM1FELHdEQTJRQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQVU7SUFFNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFbkMsMEhBQTBIO0lBQzFILDhIQUE4SDtJQUU5SCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDMUUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsS0FBSyxNQUFNLENBQUM7S0FDOUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsb0JBQW9CLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDekUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsS0FBSyxNQUFNLENBQUM7S0FDNUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDbkUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxNQUFNLENBQUM7S0FDaEc7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUVoQixDQUFDO0FBYUQsU0FBUyxhQUFhLENBQUMsUUFBK0MsRUFBRSxRQUFzQztJQUM1RyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXJELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxFQUFFLENBQUM7SUFDdEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUV0RCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsZ0JBQWdCLElBQUksRUFBRSxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFFL0MsT0FBTztRQUNMLFdBQVcsRUFBRSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJO1FBQzVDLFVBQVUsRUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUM7WUFDL0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvRixZQUFZLEVBQ1YsV0FBVyxDQUFDLHFCQUFxQixLQUFLLFdBQVcsQ0FBQyxxQkFBcUI7WUFDdkUsV0FBVyxDQUFDLG9CQUFvQixLQUFLLFdBQVcsQ0FBQyxvQkFBb0I7WUFDckUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsb0JBQW9CLENBQUM7UUFDeEQsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDbEQsYUFBYSxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDcEQsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2dCQUN0QixPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPO2FBQy9CLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxZQUFZLEVBQUU7Z0JBQ3hCLDhGQUE4RjtnQkFDOUYscUdBQXFHO2dCQUNyRyxpRUFBaUU7Z0JBQ2pFLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRztvQkFDMUIscUJBQXFCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUI7b0JBQzdFLG9CQUFvQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsb0JBQW9CO29CQUMzRSxpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQjtpQkFDdEUsQ0FBQzthQUNIO1lBQ0QsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWxFLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztTQUNuRDtRQUVELGFBQWE7UUFDYixPQUFPO0tBQ1I7SUFFUyxLQUFLLENBQUMsZ0JBQWdCO1FBQzlCLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUVoQyxvRUFBb0U7UUFDcEUsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRTtZQUMxQixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ3hFLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2IsT0FBTyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQzthQUM5QjtZQUVELHdFQUF3RTtZQUN4RSwwRUFBMEU7WUFDMUUscUVBQXFFO1NBQ3RFO1FBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFTyxLQUFLLENBQUMsb0JBQW9CLENBQUMsVUFBa0I7UUFDbkQsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUV6RCw0RUFBNEU7UUFDNUUsd0JBQXdCO1FBQ3hCLE1BQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUNyRixJQUFJLE9BQU8sRUFBRSxPQUFPLEtBQUssVUFBVSxFQUFFO1lBQ25DLE9BQU8sQ0FBQyxHQUFHLENBQUMsOEJBQThCLE9BQU8sQ0FBQyxPQUFPLDJCQUEyQixDQUFDLENBQUM7WUFDdEYsT0FBTztTQUNSO1FBRUQsTUFBTSxjQUFjLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDNUcsT0FBTyxFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDO0tBQ25EO0lBRU8sS0FBSyxDQUFDLFFBQVE7UUFDcEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1FBQ3BELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDeEUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRTdCLDRFQUE0RTtRQUM1RSx5RUFBeUU7UUFDekUsc0RBQXNEO1FBQ3RELElBQUksT0FBTyxFQUFFLE1BQU0sS0FBSyxRQUFRLEVBQUU7WUFDaEMsNkVBQTZFO1lBQzdFLGlCQUFpQjtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLCtCQUErQixDQUFDLENBQUM7U0FDbEQ7YUFBTSxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ3ZDLE9BQU87Z0JBQ0wsVUFBVSxFQUFFLEtBQUs7YUFDbEIsQ0FBQztTQUNIO2FBQU07WUFDTCxPQUFPO2dCQUNMLFVBQVUsRUFBRSxJQUFJO2dCQUNoQixJQUFJLEVBQUU7b0JBQ0osSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7b0JBQzFCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztvQkFFaEIsb0VBQW9FO29CQUNwRSw4REFBOEQ7b0JBQzlELGtFQUFrRTtvQkFDbEUsYUFBYTtvQkFFYix3QkFBd0IsRUFBRSxPQUFPLENBQUMsb0JBQW9CLEVBQUUsSUFBSSxJQUFJLEVBQUU7b0JBQ2xFLHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxzQkFBc0IsSUFBSSxFQUFFO29CQUNoRixzQkFBc0IsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxNQUFNLElBQUksRUFBRTtvQkFDNUQsbUJBQW1CLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFO29CQUV2RSw0R0FBNEc7b0JBQzVHLDhIQUE4SDtvQkFDOUgsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLElBQUksRUFBRTtpQkFDbEY7YUFDRixDQUFDO1NBQ0g7S0FDRjtJQUVPLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxXQUFtQjtRQUNuRCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUUvQyxNQUFNLHNCQUFzQixHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUM7WUFDM0QsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO1lBQ3RCLFFBQVEsRUFBRSxXQUFXO1NBQ3RCLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLENBQUM7UUFFckMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLE1BQU0sRUFBRTtZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1NBQ3ZFO1FBRUQsUUFBUSxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1lBQzVDLEtBQUssWUFBWTtnQkFDZixPQUFPLEtBQUssQ0FBQztZQUNmLEtBQUssWUFBWTtnQkFDZixPQUFPLElBQUksQ0FBQztZQUNkLEtBQUssUUFBUSxDQUFDO1lBQ2QsS0FBSyxXQUFXO2dCQUNkLE1BQU0sSUFBSSxLQUFLLENBQUMsc0JBQXNCLFdBQVcseUJBQXlCLElBQUksQ0FBQyxTQUFTLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwSTtnQkFDRSxNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixzQkFBc0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUM5RztLQUNGO0lBRU8sbUJBQW1CO1FBQ3pCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVc7UUFDNUQsTUFBTSxNQUFNLEdBQUcsb0JBQW9CLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDeEQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxPQUFPLEdBQUcsTUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO0tBQzlCO0NBQ0Y7QUFyUUQsd0RBcVFDO0FBRUQsU0FBUyxVQUFVLENBQUMsS0FBVTtJQUU1QixNQUFNLE1BQU0sR0FBRyxLQUFLLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUVuQywwSEFBMEg7SUFDMUgsOEhBQThIO0lBRTlILElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxxQkFBcUIsQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUMxRSxNQUFNLENBQUMsa0JBQWtCLENBQUMscUJBQXFCLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixLQUFLLE1BQU0sQ0FBQztLQUM5RztJQUVELElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxvQkFBb0IsQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUN6RSxNQUFNLENBQUMsa0JBQWtCLENBQUMsb0JBQW9CLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixLQUFLLE1BQU0sQ0FBQztLQUM1RztJQUVELElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRTtRQUNuRSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxLQUFLLE1BQU0sQ0FBQztLQUNoRztJQUVELE9BQU8sTUFBTSxDQUFDO0FBRWhCLENBQUM7QUFhRCxTQUFTLGFBQWEsQ0FBQyxRQUErQyxFQUFFLFFBQXNDO0lBQzVHLE9BQU8sQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUNyRCxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFFckQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUN0RCxNQUFNLFdBQVcsR0FBRyxRQUFRLENBQUMsa0JBQWtCLElBQUksRUFBRSxDQUFDO0lBRXRELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLGlCQUFpQixJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFDL0MsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixJQUFJLEVBQUUsQ0FBQztJQUUvQyxPQUFPO1FBQ0wsV0FBVyxFQUFFLFFBQVEsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLElBQUk7UUFDNUMsVUFBVSxFQUNSLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQztZQUMvRSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDO1FBQy9GLFlBQVksRUFDVixXQUFXLENBQUMscUJBQXFCLEtBQUssV0FBVyxDQUFDLHFCQUFxQjtZQUN2RSxXQUFXLENBQUMsb0JBQW9CLEtBQUssV0FBVyxDQUFDLG9CQUFvQjtZQUNyRSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsRUFBRSxvQkFBb0IsQ0FBQztRQUN4RCxXQUFXLEVBQUUsUUFBUSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsT0FBTztRQUNsRCxhQUFhLEVBQUUsUUFBUSxDQUFDLE9BQU8sS0FBSyxRQUFRLENBQUMsT0FBTztRQUNwRCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ25FLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7S0FDckYsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFrQixFQUFFLE1BQW1CO0lBQ3hELE9BQU8sS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json index 9d9abb323393a..b5e210755f57d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb": { + "602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21": { "source": { "path": "awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json", + "objectKey": "602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6": { + "f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc": { "source": { "path": "awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json", + "objectKey": "f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5": { + "472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605": { "source": { "path": "aws-cdk-eks-cluster-bottlerocket-ng-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5.json", + "objectKey": "472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json index bcdf76171b89a..b5630c3b38c59 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/aws-cdk-eks-cluster-bottlerocket-ng-test.template.json @@ -972,7 +972,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json" + "/602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json" ] ] }, @@ -1007,7 +1007,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json" + "/f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json index 8348bb6274bae..36c8c84cad7d1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngDefaultTestDeployAssert6C42FFE7.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json index 982eaefa64f77..08e97342578f9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksClusterResourceProvider7EC04E81.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json index f2d8c78e535c2..6da4c4c6ca618 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/awscdkeksclusterbottlerocketngtestawscdkawseksKubectlProviderE02BC096.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json index b8ce47e7ddcd5..3334c295278bd 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-bottlerocket-ng/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json index d4b2c9f465bd8..e59997687c474 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-bottlerocket-ng-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/f8c8cae88a0f7b3e8365a60472d52583c4da2ee27967b80773df43fa3cd490e5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/472d22c46dfe23885a333c3b0f678fea3bb7a085b48bc37ab8f584c33d03c605.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -168,10 +168,7 @@ "/aws-cdk-eks-cluster-bottlerocket-ng-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-bottlerocket-ng-test/Cluster/Role/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json index 7bebb85d179e0..250748206d212 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-bottlerocket-ng.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1552,7 +1552,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1725,7 +1725,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1948,7 +1948,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2169,7 +2169,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2387,7 +2387,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2566,7 +2566,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2623,7 +2623,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/71f37ec27bcc91052d7473953ff26acaf0809e05a170be3ea94b703361a557cb.json" + "/602a5f56132ce40b3837cfc90899cf3dfffef616ddea302f36368310f5930f21.json" ] ] }, @@ -2645,7 +2645,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2722,6 +2722,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2821,7 +2833,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3099,7 +3111,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3243,7 +3255,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/3043a1b67672745d02056ba21b9def813297bf697c51a24b94893c965615f0f6.json" + "/f4a0d15495e5534e3967ea2dbcee03861acd5cfd9e49b6997e630ce217892bbc.json" ] ] }, @@ -3286,7 +3298,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3324,7 +3336,7 @@ "path": "aws-cdk-eks-cluster-bottlerocket-ng/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3370,7 +3382,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['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) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 99% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index c9120c1926e03..286976ced219a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -111,7 +111,7 @@ def get_oci_cmd(repository, version): region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ + f"aws ecr-public get-login-password --region us-east-1 | " \ f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json index 88b044b89c570..8300824360b40 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2": { + "323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f": { "source": { "path": "awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json", + "objectKey": "323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae": { + "5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848": { "source": { "path": "awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json", + "objectKey": "5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49": { + "cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df": { "source": { "path": "aws-cdk-eks-handlers-in-vpc-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49.json", + "objectKey": "cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json index c7b8b666bc232..55a9d735753ef 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/aws-cdk-eks-handlers-in-vpc-test.template.json @@ -934,7 +934,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json" + "/323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json" ] ] }, @@ -984,7 +984,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json" + "/5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json index 5d3cb077014bb..29df24a1d6130 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpcDefaultTestDeployAssert40766711.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json index 40441cb50de4b..bbf66faafafca 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksClusterResourceProvider9260AB35.nested.template.json @@ -101,7 +101,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -236,7 +236,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -417,7 +417,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -600,7 +600,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -780,7 +780,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json index 7ccac52d0e21d..40b8835cd233e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/awscdkekshandlersinvpctestawscdkawseksKubectlProvider72227111.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json index 2a4f7c7c3bad9..a2586d100f218 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-handlers-in-vpc/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json index 4678d0be66588..5216ffe4108fe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-handlers-in-vpc-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/3a846cfa4f8b5686555d2adcd5c5be678aca9eefb4811ec4eff26d96b83eec49.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/cee66cbd8f13fe7f54a59d3ca58d1f9ee1c9a6da9cc9c9ca39def97f2cfbf8df.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -36,10 +36,7 @@ "/aws-cdk-eks-handlers-in-vpc-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-handlers-in-vpc-test/EksAllHandlersInVpcStack/DefaultVpc/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json index 78b73de15c95b..d2ff9f9b1fff1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-handlers-vpc.js.snapshot/tree.json @@ -62,7 +62,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "EksAllHandlersInVpcStack": { @@ -1017,7 +1017,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1529,7 +1529,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1766,7 +1766,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2053,7 +2053,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2338,7 +2338,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2620,7 +2620,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2817,7 +2817,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2898,7 +2898,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/6d7f62a36035930aa6da6f24fbf4411286172b5a5f99993d9ab2f4369c81b1a2.json" + "/323aaa33e7c7e5096218c737137719a45cde44b8c83992ede9a1b43117904f2f.json" ] ] }, @@ -2929,7 +2929,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3006,6 +3006,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -3105,7 +3117,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3383,7 +3395,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3527,7 +3539,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2015781075d1958d38e35d6aa73ec41a436e8fac0587130506c16af31360cfae.json" + "/5e5f54f81d1d2eea8b9f0e0b3d0e2390f842fce6ab429b22de2c0f940c73d848.json" ] ] }, @@ -3570,7 +3582,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3608,7 +3620,7 @@ "path": "aws-cdk-eks-handlers-in-vpc/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3654,7 +3666,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['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) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js similarity index 55% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js index 1d08e9d7b865b..c9dc1b8d2c19a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -256,8 +256,8 @@ function analyzeUpdate(oldProps, newProps) { const oldEnc = oldProps.encryptionConfig || {}; return { replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), @@ -270,4 +270,4 @@ function analyzeUpdate(oldProps, newProps) { function setsEqual(first, second) { return first.size === second.size && [...first].every((e) => second.has(e)); } -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts similarity index 98% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts index e6930b7844d32..4b7fdda6d1dd1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -326,8 +326,8 @@ function analyzeUpdate(oldProps: Partial, newProps return { replaceName: newProps.name !== oldProps.name, replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py similarity index 89% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py index a7b26b264118b..286976ced219a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -6,7 +6,6 @@ import shutil import tempfile import zipfile -from urllib.parse import urlparse, unquote logger = logging.getLogger() logger.setLevel(logging.INFO) @@ -95,26 +94,25 @@ def helm_handler(event, context): def get_oci_cmd(repository, version): # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' - registry = repository.rsplit('/', 1)[0].replace('oci://', '') + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() - if re.fullmatch(private_ecr_pattern, registry) is not None: + if private_registry['registry'] is not None: logger.info("Found AWS private repository") - 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" + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" ] - elif registry.startswith(public_ecr): + elif public_registry['registry'] is not None: logger.info("Found AWS public repository, will use default region as deployment") region = os.environ.get('AWS_REGION', 'us-east-1') cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" ] else: logger.error("OCI repository format not recognized, falling back to helm pull") diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json index c96b2ce8495ef..10ebb34df6932 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e": { + "a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b": { "source": { "path": "awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json", + "objectKey": "a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989": { + "1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837": { "source": { "path": "awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json", + "objectKey": "1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab": { + "a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137": { "source": { "path": "aws-cdk-eks-cluster-private-endpoint-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab.json", + "objectKey": "a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json index e3542cd246d0f..95fc9ba0ebba6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/aws-cdk-eks-cluster-private-endpoint-test.template.json @@ -909,7 +909,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json" + "/a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json" ] ] }, @@ -944,7 +944,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json" + "/1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json index 0cedfa6de9dfe..14657cf84d7b9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointDefaultTestDeployAssert3C16DBEA.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json index a51e8c9e7215f..4d2bc59791218 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksClusterResourceProvider67118CB1.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json index 232c040f9337b..cc6d89c4e5bf6 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/awscdkeksclusterprivateendpointtestawscdkawseksKubectlProvider421F287E.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json index c1b77c8108a74..07cb844511a09 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-private-endpoint/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json index cde3142275691..1dda241f27a5e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-private-endpoint-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/5ba2b041eec65cdf5d2382e1e12a8cb1576ec0e47352c39ba040b33cecddd2ab.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a9f315c998f5e5adceb3622a38be1e2c87b491c01978168eb8699d5ebe940137.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -168,10 +168,7 @@ "/aws-cdk-eks-cluster-private-endpoint-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-private-endpoint-test/Cluster/Role/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json index 21844ef06085c..b3f20eb5672a8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster-private-endpoint.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1455,7 +1455,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1628,7 +1628,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1851,7 +1851,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2072,7 +2072,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2290,7 +2290,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2469,7 +2469,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2526,7 +2526,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/c48cc5dc50de353455d7c81c66e9a3b94e3e31fe9fb5e198c917ed652e8d500e.json" + "/a7eab24563c84871b9595c7f0cab44a26fdb5fd2c4b18e18e6b5f040da855b4b.json" ] ] }, @@ -2548,7 +2548,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2625,6 +2625,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2724,7 +2736,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3002,7 +3014,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3146,7 +3158,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/becb250c0b730554cf1721996e6dacde9acf883666917d84e9297f19fff30989.json" + "/1a26a8f46752d564666f4e1c76938eb1338d79a9b65f4bf52da9ed8ad85aa837.json" ] ] }, @@ -3189,7 +3201,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3227,7 +3239,7 @@ "path": "aws-cdk-eks-cluster-private-endpoint/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3273,7 +3285,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..5f4ba6c9291d8 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index 5cefa4cfa936b..6cab68362ec21 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip similarity index 67% rename from packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip rename to packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip index 298edd40a09fc..6b4e14c2e2d00 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/asset.c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json index e05b8a67fb222..fafedf85d4a75 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -57,29 +57,29 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } } }, - "5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510": { + "c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc": { "source": { - "path": "asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip", + "path": "asset.c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip", "packaging": "file" }, "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip", + "objectKey": "c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } @@ -141,7 +141,7 @@ } } }, - "5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a": { + "67a3aa529ec1ed1816a4cf80820b64e8664fc647e3c49f45996ed25b332e7d07": { "source": { "path": "awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json", "packaging": "file" @@ -149,13 +149,13 @@ "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json", + "objectKey": "67a3aa529ec1ed1816a4cf80820b64e8664fc647e3c49f45996ed25b332e7d07.json", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } } }, - "135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273": { + "6782a2a042fa36c961aad9bb00a06c22bfc03046118bf097208ad738af93cbe7": { "source": { "path": "aws-cdk-eks-cluster-test.template.json", "packaging": "file" @@ -163,7 +163,7 @@ "destinations": { "current_account-us-east-1": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1", - "objectKey": "135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273.json", + "objectKey": "6782a2a042fa36c961aad9bb00a06c22bfc03046118bf097208ad738af93cbe7.json", "region": "us-east-1", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-us-east-1" } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json index c9c8b8f055c29..ed7cc1de372b2 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/aws-cdk-eks-cluster-test.template.json @@ -3019,11 +3019,11 @@ "Fn::Join": [ "", [ - "[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"data\":{\"clusterName\":\"", + "[{\"apiVersion\":\"v1\",\"kind\":\"ConfigMap\",\"metadata\":{\"name\":\"chart-config-map-c820e51c\",\"labels\":{\"aws.cdk.eks/prune-c89c99db0e333353528b2e912b1fb988b6870edc75\":\"\"}},\"data\":{\"clusterName\":\"", { "Ref": "Cluster9EE0221C" }, - "\"},\"immutable\":false,\"metadata\":{\"name\":\"chart-config-map-c820e51c\",\"labels\":{\"aws.cdk.eks/prune-c89c99db0e333353528b2e912b1fb988b6870edc75\":\"\"}}}]" + "\"},\"immutable\":false}]" ] ] }, @@ -3406,7 +3406,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "/5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json" + "/67a3aa529ec1ed1816a4cf80820b64e8664fc647e3c49f45996ed25b332e7d07.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json index c5a73c6555dd8..1f919c65eaa58 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclusterDefaultTestDeployAssertFBF4B356.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json index b758aa6d3170d..5bd4e0d860851 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/awscdkeksclustertestawscdkawseksKubectlProviderE05943BF.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -125,7 +137,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -174,7 +186,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "S3Key": "5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip" + "S3Key": "c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip" }, "Description": "/opt/awscli/aws" } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json index 03a31d112b00c..e8db188b6ecf8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json index e3236a29bd07c..3bea8fd594551 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-us-east-1", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-us-east-1", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/135550969dc86be479785b50f9d5aae26cb7cd8b06dfac538d0a2ec138cd0273.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1/6782a2a042fa36c961aad9bb00a06c22bfc03046118bf097208ad738af93cbe7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json index a7f52f35694fd..e294b91873431 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-cluster.js.snapshot/tree.json @@ -798,7 +798,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.85" + "version": "2.0.108" } }, "Cluster": { @@ -1197,7 +1197,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } }, "KubectlReadyBarrier": { @@ -5557,7 +5557,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } } }, @@ -5632,7 +5632,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -5709,6 +5709,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -5841,7 +5853,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -5930,7 +5942,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "s3Key": "5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip" + "s3Key": "c9455aefa243f3cd7a810b3f6df8ed37e457d3e1d046353da27c4aa13551d4dc.zip" }, "description": "/opt/awscli/aws" } @@ -6259,7 +6271,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-us-east-1" }, - "/5ae9306474c5c23767a5fd25baabe8b6bc0784ab276ad7318f1a2152323b253a.json" + "/67a3aa529ec1ed1816a4cf80820b64e8664fc647e3c49f45996ed25b332e7d07.json" ] ] }, @@ -6302,7 +6314,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } }, "SsmParameterValue:--aws--service--eks--optimized-ami--1.24--amazon-linux-2--recommended--image_id:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { @@ -6606,7 +6618,7 @@ "path": "aws-cdk-eks-cluster/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } }, "DeployAssert": { @@ -6652,7 +6664,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.259" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py deleted file mode 100644 index 1d86804bd67d8..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index d7cb484796289..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/helm/__init__.py new file mode 100644 index 0000000000000..34481f86a81d7 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/helm/__init__.py @@ -0,0 +1,190 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + skip_crds = props.get('SkipCrds', False) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None, skip_crds = False): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if skip_crds: + cmnd.append('--skip-crds') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index e3828a91bf834..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index 83790ed746b07..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json index f20e6d04df408..7264badd715f4 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,15 +27,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -53,15 +53,15 @@ } } }, - "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee": { + "92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02": { "source": { - "path": "asset.563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee", + "path": "asset.92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip", + "objectKey": "92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -92,7 +92,7 @@ } } }, - "d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54": { + "013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f": { "source": { "path": "awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json", + "objectKey": "013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d": { + "228d4002689856d23e839fb690137b828253b51ab0ba4bd84b6ff0d65e1c23ca": { "source": { "path": "awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json", + "objectKey": "228d4002689856d23e839fb690137b828253b51ab0ba4bd84b6ff0d65e1c23ca.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7": { + "efe0e6bc3feeea333864740608c04489da76bd20395f877733932bad8ccc7a66": { "source": { "path": "aws-cdk-eks-helm-test.template.json", "packaging": "file" @@ -126,7 +126,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7.json", + "objectKey": "efe0e6bc3feeea333864740608c04489da76bd20395f877733932bad8ccc7a66.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json index 8867747159819..29e21c9df3b32 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/aws-cdk-eks-helm-test.template.json @@ -973,6 +973,38 @@ "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" }, + "ClustercharttestskipcrdinstallationB8323954": { + "Type": "Custom::AWSCDK-EKS-HelmChart", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "awscdkawseksKubectlProviderNestedStackawscdkawseksKubectlProviderNestedStackResourceA7AEBA6B", + "Outputs.awscdkekshelmtestawscdkawseksKubectlProviderframeworkonEvent9D93C644Arn" + ] + }, + "ClusterName": { + "Ref": "Cluster9EE0221C" + }, + "RoleArn": { + "Fn::GetAtt": [ + "ClusterCreationRole360249B6", + "Arn" + ] + }, + "Release": "lambda-chart-release", + "Chart": "lambda-chart", + "Version": "v0.1.4", + "Namespace": "ack-system", + "Repository": "oci://public.ecr.aws/aws-controllers-k8s/lambda-chart", + "CreateNamespace": true, + "SkipCrds": true + }, + "DependsOn": [ + "ClusterKubectlReadyBarrier200052AF" + ], + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "awscdkawseksClusterResourceProviderNestedStackawscdkawseksClusterResourceProviderNestedStackResource9827C454": { "Type": "AWS::CloudFormation::Stack", "Properties": { @@ -992,7 +1024,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json" + "/013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json" ] ] }, @@ -1027,7 +1059,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json" + "/228d4002689856d23e839fb690137b828253b51ab0ba4bd84b6ff0d65e1c23ca.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json index bf373fcb2d4ba..2993275ee1385 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmDefaultTestDeployAssert044A589A.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json index 4187fe2aae9e4..cf76c0a4dc67e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksClusterResourceProviderB64048CD.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json index 0fadf56a7829b..1d645caa5c219 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/awscdkekshelmtestawscdkawseksKubectlProvider207F42E4.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -133,7 +145,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip" + "S3Key": "92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out index d8b441d447f8a..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"29.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json index 467521ffceb4e..dc7128ee4bbc7 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-helm/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json index 3fcf4ec11976d..1d20823d73040 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-helm-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/9a8f080c5f01d52249f35aadae7fa8b7400e3d8d799422e7ce845995c7914eb7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/efe0e6bc3feeea333864740608c04489da76bd20395f877733932bad8ccc7a66.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -255,6 +255,12 @@ "data": "Clustercharttestocichartdifferentreleasename6D3FD1A1" } ], + "/aws-cdk-eks-helm-test/Cluster/chart-test-skip-crd-installation/Resource/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "ClustercharttestskipcrdinstallationB8323954" + } + ], "/aws-cdk-eks-helm-test/@aws-cdk--aws-eks.ClusterResourceProvider/NodeProxyAgentLayer/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json index 2d82b8334a8e8..3fb0075876cea 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.js.snapshot/tree.json @@ -755,7 +755,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.78" + "version": "2.0.100" } }, "Cluster": { @@ -1019,7 +1019,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1306,6 +1306,34 @@ "fqn": "@aws-cdk/aws-eks.HelmChart", "version": "0.0.0" } + }, + "chart-test-skip-crd-installation": { + "id": "chart-test-skip-crd-installation", + "path": "aws-cdk-eks-helm-test/Cluster/chart-test-skip-crd-installation", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-eks-helm-test/Cluster/chart-test-skip-crd-installation/Resource", + "children": { + "Default": { + "id": "Default", + "path": "aws-cdk-eks-helm-test/Cluster/chart-test-skip-crd-installation/Resource/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-eks.HelmChart", + "version": "0.0.0" + } } }, "constructInfo": { @@ -1511,7 +1539,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1684,7 +1712,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2525,7 +2553,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } } }, @@ -2582,7 +2610,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/d0ed18f830c9e49d64521037c4c2d872500fd7df2bc7d2d32ff2f59446d69f54.json" + "/013c608e5aa3f9b7c08666064fdbc7d257f19866887e2ea155c5b189fdfd6f0f.json" ] ] }, @@ -2604,7 +2632,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2681,6 +2709,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2821,7 +2861,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "563343f1aee007876e917a1bf685464df7e56190033d5ae5b9fd14d498e9c5ee.zip" + "s3Key": "92ea03f8b2e779503519f7781d06c03f95b46863db85f5c50a4e7debfd04be02.zip" }, "role": { "Fn::GetAtt": [ @@ -3243,7 +3283,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/dcb6b679999203518cf8e747008ba448af7bc6502f87c2b869ca87565786b67d.json" + "/228d4002689856d23e839fb690137b828253b51ab0ba4bd84b6ff0d65e1c23ca.json" ] ] }, @@ -3286,7 +3326,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "ChartAsset": { @@ -3350,7 +3390,7 @@ "path": "aws-cdk-eks-helm/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } }, "DeployAssert": { @@ -3396,7 +3436,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.209" + "version": "10.1.252" } } }, 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 index afda984814487..f266123a6c6c8 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.ts +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-helm-asset.ts @@ -76,6 +76,17 @@ class EksClusterStack extends Stack { namespace: 'ack-system', createNamespace: true, }); + + // testing the disable mechanism of the installation of CRDs + this.cluster.addHelmChart('test-skip-crd-installation', { + chart: 'lambda-chart', + release: 'lambda-chart-release', + repository: 'oci://public.ecr.aws/aws-controllers-k8s/lambda-chart', + version: 'v0.1.4', + namespace: 'ack-system', + createNamespace: true, + skipCrds: true, + }); } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['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) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztTQUN0RTtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2FBQ3ZCLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7Z0JBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7YUFDeEM7WUFBQSxDQUFDO1lBQ0YsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUN4Qiw4RkFBOEY7Z0JBQzlGLHFHQUFxRztnQkFDckcsaUVBQWlFO2dCQUNqRSxNQUFNLENBQUMsa0JBQWtCLEdBQUc7b0JBQzFCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMscUJBQXFCO29CQUM3RSxvQkFBb0IsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQjtvQkFDM0UsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBaUI7aUJBQ3RFLENBQUM7YUFDSDtZQUNELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUVsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7U0FDbkQ7UUFFRCxhQUFhO1FBQ2IsT0FBTztLQUNSO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEMsb0VBQW9FO1FBQ3BFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDMUIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNiLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7YUFDOUI7WUFFRCx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLHFFQUFxRTtTQUN0RTtRQUVELE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ3hCO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUFDLFVBQWtCO1FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFFekQsNEVBQTRFO1FBQzVFLHdCQUF3QjtRQUN4QixNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDckYsSUFBSSxPQUFPLEVBQUUsT0FBTyxLQUFLLFVBQVUsRUFBRTtZQUNuQyxPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixPQUFPLENBQUMsT0FBTywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3RGLE9BQU87U0FDUjtRQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzVHLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUNuRDtJQUVPLEtBQUssQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUU3Qiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLHNEQUFzRDtRQUN0RCxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ2hDLDZFQUE2RTtZQUM3RSxpQkFBaUI7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1NBQ2xEO2FBQU0sSUFBSSxPQUFPLEVBQUUsTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUN2QyxPQUFPO2dCQUNMLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUM7U0FDSDthQUFNO1lBQ0wsT0FBTztnQkFDTCxVQUFVLEVBQUUsSUFBSTtnQkFDaEIsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUMxQixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBRWhCLG9FQUFvRTtvQkFDcEUsOERBQThEO29CQUM5RCxrRUFBa0U7b0JBQ2xFLGFBQWE7b0JBRWIsd0JBQXdCLEVBQUUsT0FBTyxDQUFDLG9CQUFvQixFQUFFLElBQUksSUFBSSxFQUFFO29CQUNsRSxzQkFBc0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCLEVBQUUsc0JBQXNCLElBQUksRUFBRTtvQkFDaEYsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxJQUFJLEVBQUU7b0JBQzVELG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtvQkFFdkUsNEdBQTRHO29CQUM1Ryw4SEFBOEg7b0JBQzlILHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLEVBQUU7aUJBQ2xGO2FBQ0YsQ0FBQztTQUNIO0tBQ0Y7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQUMsV0FBbUI7UUFDbkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFL0MsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsV0FBVztZQUN0QixRQUFRLEVBQUUsV0FBVztTQUN0QixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUU7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUN2RTtRQUVELFFBQVEsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUM1QyxLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxLQUFLLENBQUM7WUFDZixLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxJQUFJLENBQUM7WUFDZCxLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssV0FBVztnQkFDZCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixXQUFXLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEk7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDOUc7S0FDRjtJQUVPLG1CQUFtQjtRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXO1FBQzVELE1BQU0sTUFBTSxHQUFHLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsT0FBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztLQUM5QjtDQUNGO0FBM1FELHdEQTJRQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQVU7SUFFNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFbkMsMEhBQTBIO0lBQzFILDhIQUE4SDtJQUU5SCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDMUUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsS0FBSyxNQUFNLENBQUM7S0FDOUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsb0JBQW9CLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDekUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsS0FBSyxNQUFNLENBQUM7S0FDNUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDbkUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxNQUFNLENBQUM7S0FDaEc7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUVoQixDQUFDO0FBYUQsU0FBUyxhQUFhLENBQUMsUUFBK0MsRUFBRSxRQUFzQztJQUM1RyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXJELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxFQUFFLENBQUM7SUFDdEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUV0RCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsZ0JBQWdCLElBQUksRUFBRSxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFFL0MsT0FBTztRQUNMLFdBQVcsRUFBRSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJO1FBQzVDLFVBQVUsRUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7WUFDL0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUMvRyxZQUFZLEVBQ1YsV0FBVyxDQUFDLHFCQUFxQixLQUFLLFdBQVcsQ0FBQyxxQkFBcUI7WUFDdkUsV0FBVyxDQUFDLG9CQUFvQixLQUFLLFdBQVcsQ0FBQyxvQkFBb0I7WUFDckUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsb0JBQW9CLENBQUM7UUFDeEQsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDbEQsYUFBYSxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDcEQsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json index b7ee69e29a954..75ac985d5ddf4 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -105,7 +105,7 @@ } } }, - "160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845": { + "de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7": { "source": { "path": "awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json", + "objectKey": "de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f": { + "20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36": { "source": { "path": "awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json", + "objectKey": "20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe": { + "2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7": { "source": { "path": "aws-cdk-eks-cluster-inference-test.template.json", "packaging": "file" @@ -139,7 +139,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe.json", + "objectKey": "2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json index 0262458e19fe8..1ec240045c027 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/aws-cdk-eks-cluster-inference-test.template.json @@ -1298,7 +1298,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json" + "/de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json" ] ] }, @@ -1333,7 +1333,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json" + "/20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json index 56eece9571236..7e029d4327e6b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksClusterResourceProviderFE14F3C4.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json index bacefdbe9de0d..de3653653c8b0 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinferencetestawscdkawseksKubectlProviderB4348345.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json index a58558fc71f25..30e706a4b7d8e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/awscdkeksclusterinterenceDefaultTestDeployAssert715EC778.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json index 5f391b6d8d18e..b31cbc02e9241 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-cluster-interence/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json index 60c9855e3a5b2..a106a296b0a16 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-cluster-inference-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/131e26ab8ac8c0fbd4ab469fe6480d8b75772cc44d08a78150d6ada479b1e1fe.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/2aea21fa82e8bde5c28e5a01f0449e50a6e440d6a9ecf94c8376af3ab7e40ac7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -162,10 +162,7 @@ "/aws-cdk-eks-cluster-inference-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-cluster-inference-test/Cluster/Role/Resource": [ @@ -259,26 +256,6 @@ } ], "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/InstanceSecurityGroup": [ - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, - { - "type": "aws:cdk:warning", - "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" - }, { "type": "aws:cdk:warning", "data": "Ignoring Egress rule since 'allowAllOutbound' is set to true; To add customized rules, set allowAllOutbound=false on the SecurityGroup" @@ -335,10 +312,7 @@ "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/LaunchConfig": [ { "type": "aws:cdk:logicalId", - "data": "ClusterInferenceInstancesLaunchConfig03BF48FE", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "ClusterInferenceInstancesLaunchConfig03BF48FE" } ], "/aws-cdk-eks-cluster-inference-test/Cluster/InferenceInstances/ASG": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json index 2fe38766058b2..772bf54948b21 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-inference.js.snapshot/tree.json @@ -697,7 +697,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "Cluster": { @@ -990,7 +990,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1968,7 +1968,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2141,7 +2141,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2364,7 +2364,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2585,7 +2585,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2803,7 +2803,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2982,7 +2982,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -3039,7 +3039,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/160c5063e51e97adff360ac4e9bf20abf8cc478d5aaf57a42f93b48f6a2b4845.json" + "/de84c9c4d1f67fa4adb8cb3b1e0aa899ce4113c4059d117e6fcd0fc2605e55a7.json" ] ] }, @@ -3061,7 +3061,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -3138,6 +3138,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -3237,7 +3249,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3515,7 +3527,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3659,7 +3671,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/bbe941dd0ff744fff9cc3c2f087e08a3259311e76c228f7197c0a3bf7edc550f.json" + "/20f7730358961f0e97cf67aa93015ece8a2943b516dcd91b95b20e14b01ead36.json" ] ] }, @@ -3702,7 +3714,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "awscdkeksclusterinferencetestClusterEBBBA1AC-AlbController": { @@ -4184,7 +4196,7 @@ "path": "aws-cdk-eks-cluster-interence/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -4230,7 +4242,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/__entrypoint__.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/__entrypoint__.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/__entrypoint__.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/__entrypoint__.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/diff.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/diff.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/diff.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/diff.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js similarity index 58% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js index acdacae4e8175..1edead6dd3913 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/external.js +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/external.js @@ -91,4 +91,4 @@ exports.external = { addClientIDToOpenIDConnectProvider: (req) => iam().addClientIDToOpenIDConnectProvider(req).promise(), removeClientIDFromOpenIDConnectProvider: (req) => iam().removeClientIDFromOpenIDConnectProvider(req).promise(), }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZXJuYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJleHRlcm5hbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSwyQkFBMkI7QUFDM0IsMkJBQTJCO0FBQzNCLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFFL0IsSUFBSSxNQUFlLENBQUM7QUFFcEIsU0FBUyxHQUFHO0lBQ1YsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUFFLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUFFO0lBQ3hDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsR0FBRyxJQUFXO0lBQ2hELHNDQUFzQztJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxTQUFpQjtJQUVqRCxPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUV2RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU8sRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLDRDQUE0QyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDL0U7UUFFRCxnQkFBUSxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFB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R0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLENBQUM7SUFFOUYsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELHlDQUF5QztBQUN6Qyw0QkFBNEI7QUFDZixRQUFBLFFBQVEsR0FBRztJQUN0QixrQkFBa0I7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDbEIsMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEksMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEkscUNBQXFDLEVBQUUsQ0FBQyxHQUF5RCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDaEssa0NBQWtDLEVBQUUsQ0FBQyxHQUFzRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQ0FBa0MsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDdkosdUNBQXVDLEVBQUUsQ0FBQyxHQUEyRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1Q0FBdUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7Q0FDdkssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG5pbXBvcnQgeyBYNTA5Q2VydGlmaWNhdGUgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgKiBhcyB0bHMgZnJvbSAndGxzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5sZXQgY2xpZW50OiBhd3MuSUFNO1xuXG5mdW5jdGlvbiBpYW0oKSB7XG4gIGlmICghY2xpZW50KSB7IGNsaWVudCA9IG5ldyBhd3MuSUFNKCk7IH1cbiAgcmV0dXJuIGNsaWVudDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZ2dlcihmbXQ6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coZm10LCAuLi5hcmdzKTtcbn1cblxuLyoqXG4gKiBEb3dubG9hZHMgdGhlIENBIHRodW1icHJpbnQgZnJvbSB0aGUgaXNzdWVyIFVSTFxuICovXG5hc3luYyBmdW5jdGlvbiBkb3dubG9hZFRodW1icHJpbnQoaXNzdWVyVXJsOiBzdHJpbmcpIHtcblxuICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigob2ssIGtvKSA9PiB7XG4gICAgY29uc3QgcHVybCA9IHVybC5wYXJzZShpc3N1ZXJVcmwpO1xuICAgIGNvbnN0IHBvcnQgPSBwdXJsLnBvcnQgPyBwYXJzZUludChwdXJsLnBvcnQsIDEwKSA6IDQ0MztcblxuICAgIGlmICghcHVybC5ob3N0KSB7XG4gICAgICByZXR1cm4ga28obmV3IEVycm9yKGB1bmFibGUgdG8gZGV0ZXJtaW5lIGhvc3QgZnJvbSBpc3N1ZXIgdXJsICR7aXNzdWVyVXJsfWApKTtcbiAgICB9XG5cbiAgICBleHRlcm5hbC5sb2coYEZldGNoaW5nIHg1MDkgY2VydGlmaWNhdGUgY2hhaW4gZnJvbSBpc3N1ZXIgJHtpc3N1ZXJVcmx9YCk7XG5cbiAgICBjb25zdCBzb2NrZXQgPSB0bHMuY29ubmVjdChwb3J0LCBwdXJsLmhvc3QsIHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSwgc2VydmVybmFtZTogcHVybC5ob3N0IH0pO1xuICAgIHNvY2tldC5vbmNlKCdlcnJvcicsIGtvKTtcblxuICAgIHNvY2tldC5vbmNlKCdzZWN1cmVDb25uZWN0JywgKCkgPT4ge1xuICAgICAgbGV0IGNlcnQgPSBzb2NrZXQuZ2V0UGVlclg1MDlDZXJ0aWZpY2F0ZSgpO1xuICAgICAgaWYgKCFjZXJ0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJldHJpZXZlIFg1MDkgY2VydGlmaWNhdGUgZnJvbSBob3N0ICR7cHVybC5ob3N0fWApO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGNlcnQuaXNzdWVyQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgcHJpbnRDZXJ0aWZpY2F0ZShjZXJ0KTtcbiAgICAgICAgY2VydCA9IGNlcnQuaXNzdWVyQ2VydGlmaWNhdGU7XG4gICAgICB9XG4gICAgICBjb25zdCB2YWxpZFRvID0gbmV3IERhdGUoY2VydC52YWxpZFRvKTtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlVmFsaWRpdHkgPSBnZXRDZXJ0aWZpY2F0ZVZhbGlkaXR5KHZhbGlkVG8pO1xuXG4gICAgICBpZiAoY2VydGlmaWNhdGVWYWxpZGl0eSA8IDApIHtcbiAgICAgICAgcmV0dXJuIGtvKG5ldyBFcnJvcihgVGhlIGNlcnRpZmljYXRlIGhhcyBhbHJlYWR5IGV4cGlyZWQgb246ICR7dmFsaWRUby50b1VUQ1N0cmluZygpfWApKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FybmluZyB1c2VyIGlmIGNlcnRpZmljYXRlIHZhbGlkaXR5IGlzIGV4cGlyaW5nIHdpdGhpbiA2IG1vbnRoc1xuICAgICAgaWYgKGNlcnRpZmljYXRlVmFsaWRpdHkgPCAxODApIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgY29uc29sZS53YXJuKGBUaGUgcm9vdCBjZXJ0aWZpY2F0ZSBvYnRhaW5lZCB3b3VsZCBleHBpcmUgaW4gJHtjZXJ0aWZpY2F0ZVZhbGlkaXR5fSBkYXlzIWApO1xuICAgICAgfVxuXG4gICAgICBzb2NrZXQuZW5kKCk7XG5cbiAgICAgIGNvbnN0IHRodW1icHJpbnQgPSBleHRyYWN0VGh1bWJwcmludChjZXJ0KTtcbiAgICAgIGV4dGVybmFsLmxvZyhgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IHRodW1icHJpbnQgZm9yICR7aXNzdWVyVXJsfSBpcyAke3RodW1icHJpbnR9YCk7XG5cbiAgICAgIG9rKHRodW1icHJpbnQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFRodW1icHJpbnQoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIHJldHVybiBjZXJ0LmZpbmdlcnByaW50LnNwbGl0KCc6Jykuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIHByaW50Q2VydGlmaWNhdGUoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIGV4dGVybmFsLmxvZygnLS0tLS0tLS0tLS0tLUJFR0lOIENFUlQtLS0tLS0tLS0tLS0tLS0tJyk7XG4gIGV4dGVybmFsLmxvZyhgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0KX1gKTtcbiAgZXh0ZXJuYWwubG9nKGBWYWxpZCBUbzogJHtjZXJ0LnZhbGlkVG99YCk7XG4gIGlmIChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKSB7XG4gICAgZXh0ZXJuYWwubG9nKGBJc3N1ZXIgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKX1gKTtcbiAgfVxuICBleHRlcm5hbC5sb2coYElzc3VlcjogJHtjZXJ0Lmlzc3Vlcn1gKTtcbiAgZXh0ZXJuYWwubG9nKGBTdWJqZWN0OiAke2NlcnQuc3ViamVjdH1gKTtcbiAgZXh0ZXJuYWwubG9nKCctLS0tLS0tLS0tLS0tRU5EIENFUlQtLS0tLS0tLS0tLS0tLS0tLS0nKTtcbn1cblxuLyoqXG4gKiBUbyBnZXQgdGhlIHZhbGlkaXR5IHRpbWVsaW5lIGZvciB0aGUgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSBjZXJ0RGF0ZSBUaGUgdmFsaWQgdG8gZGF0ZSBmb3IgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIGRheXMgdGhlIGNlcnRpZmljYXRlIGlzIHZhbGlkIHdydCBjdXJyZW50IGRhdGVcbiAqL1xuZnVuY3Rpb24gZ2V0Q2VydGlmaWNhdGVWYWxpZGl0eShjZXJ0RGF0ZTogRGF0ZSk6IE51bWJlciB7XG4gIGNvbnN0IG1pbGxpc2Vjb25kc0luRGF5ID0gMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIGNvbnN0IHZhbGlkaXR5ID0gTWF0aC5yb3VuZCgoY2VydERhdGUuZ2V0VGltZSgpIC0gY3VycmVudERhdGUuZ2V0VGltZSgpKSAvIG1pbGxpc2Vjb25kc0luRGF5KTtcblxuICByZXR1cm4gdmFsaWRpdHk7XG59XG5cbi8vIGFsbG93cyB1bml0IHRlc3QgdG8gcmVwbGFjZSB3aXRoIG1vY2tzXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5leHBvcnQgY29uc3QgZXh0ZXJuYWwgPSB7XG4gIGRvd25sb2FkVGh1bWJwcmludCxcbiAgbG9nOiBkZWZhdWx0TG9nZ2VyLFxuICBjcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uQ3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuY3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICBkZWxldGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uRGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuZGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICB1cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50OiAocmVxOiBhd3MuSUFNLlVwZGF0ZU9wZW5JRENvbm5lY3RQcm92aWRlclRodW1icHJpbnRSZXF1ZXN0KSA9PiBpYW0oKS51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHJlcSkucHJvbWlzZSgpLFxuICBhZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyOiAocmVxOiBhd3MuSUFNLkFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXJSZXF1ZXN0KSA9PiBpYW0oKS5hZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICByZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uUmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkucmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxufTsiXX0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZXJuYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJleHRlcm5hbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFTQSwyQkFBMkI7QUFDM0IsMkJBQTJCO0FBQzNCLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFFL0IsSUFBSSxNQUFlLENBQUM7QUFFcEIsU0FBUyxHQUFHO0lBQ1YsSUFBSSxDQUFDLE1BQU0sRUFBRTtRQUFFLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztLQUFFO0lBQ3hDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFXLEVBQUUsR0FBRyxJQUFXO0lBQ2hELHNDQUFzQztJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0FBQzVCLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxTQUFpQjtJQUVqRCxPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO1FBQ3BDLE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUV2RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU8sRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLDRDQUE0QyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7U0FDL0U7UUFFRCxnQkFBUSxDQUFDLEdBQUcsQ0FBQywrQ0FBK0MsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFB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R0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxHQUFHLFdBQVcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQixDQUFDLENBQUM7SUFFOUYsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELHlDQUF5QztBQUN6Qyw0QkFBNEI7QUFDZixRQUFBLFFBQVEsR0FBRztJQUN0QixrQkFBa0I7SUFDbEIsR0FBRyxFQUFFLGFBQWE7SUFDbEIsMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEksMkJBQTJCLEVBQUUsQ0FBQyxHQUErQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDbEkscUNBQXFDLEVBQUUsQ0FBQyxHQUF5RCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDaEssa0NBQWtDLEVBQUUsQ0FBQyxHQUFzRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQ0FBa0MsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7SUFDdkosdUNBQXVDLEVBQUUsQ0FBQyxHQUEyRCxFQUFFLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1Q0FBdUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUU7Q0FDdkssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGlzdGFuYnVsIGlnbm9yZSBmaWxlICovXG4vLyB0aGUgWDUwOSBjZXJ0aWZpY2F0ZSBBUEkgaXMgYXZhaWxhYmxlIG9ubHkgaW4gbm9kZTE2LlxuLy8gc2luY2Ugd2UgY29tcGlsZSB0aGUgcmVwbyBhZ2FpbnN0IG5vZGUgMTQsIHR5cGVjaGVja2luZyBpdCB3aWxsIGZhaWwuXG4vLyBpdHMgY3VycmVudGx5IHRvbyBjb21wbGV4IHRvIGNvbmZpZ3VyZSBub2RlMTYgb25seSBvbiB0aGlzXG4vLyBmaWxlIChqc2lpIGRvZXNuJ3Qgc3VwcG9ydCBjdXN0b20gdHNjb25maWcpXG4vLyBzbyB3ZSBkaXNhYmxlIHR5cGVjaGVja2luZy4gZG9uJ3Qgd29ycnksIHdlIGhhdmUgc3VmZmljaWVudCBpbnRlZyB0ZXN0cyB0aGF0XG4vLyB2YWxpZGF0ZSB0aGlzIGNvZGUgZG9lc24ndCBicmVhay5cbi8vIEB0cy1ub2NoZWNrXG5pbXBvcnQgeyBYNTA5Q2VydGlmaWNhdGUgfSBmcm9tICdub2RlOmNyeXB0byc7XG5pbXBvcnQgKiBhcyB0bHMgZnJvbSAndGxzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5sZXQgY2xpZW50OiBhd3MuSUFNO1xuXG5mdW5jdGlvbiBpYW0oKSB7XG4gIGlmICghY2xpZW50KSB7IGNsaWVudCA9IG5ldyBhd3MuSUFNKCk7IH1cbiAgcmV0dXJuIGNsaWVudDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZ2dlcihmbXQ6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coZm10LCAuLi5hcmdzKTtcbn1cblxuLyoqXG4gKiBEb3dubG9hZHMgdGhlIENBIHRodW1icHJpbnQgZnJvbSB0aGUgaXNzdWVyIFVSTFxuICovXG5hc3luYyBmdW5jdGlvbiBkb3dubG9hZFRodW1icHJpbnQoaXNzdWVyVXJsOiBzdHJpbmcpIHtcblxuICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigob2ssIGtvKSA9PiB7XG4gICAgY29uc3QgcHVybCA9IHVybC5wYXJzZShpc3N1ZXJVcmwpO1xuICAgIGNvbnN0IHBvcnQgPSBwdXJsLnBvcnQgPyBwYXJzZUludChwdXJsLnBvcnQsIDEwKSA6IDQ0MztcblxuICAgIGlmICghcHVybC5ob3N0KSB7XG4gICAgICByZXR1cm4ga28obmV3IEVycm9yKGB1bmFibGUgdG8gZGV0ZXJtaW5lIGhvc3QgZnJvbSBpc3N1ZXIgdXJsICR7aXNzdWVyVXJsfWApKTtcbiAgICB9XG5cbiAgICBleHRlcm5hbC5sb2coYEZldGNoaW5nIHg1MDkgY2VydGlmaWNhdGUgY2hhaW4gZnJvbSBpc3N1ZXIgJHtpc3N1ZXJVcmx9YCk7XG5cbiAgICBjb25zdCBzb2NrZXQgPSB0bHMuY29ubmVjdChwb3J0LCBwdXJsLmhvc3QsIHsgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZSwgc2VydmVybmFtZTogcHVybC5ob3N0IH0pO1xuICAgIHNvY2tldC5vbmNlKCdlcnJvcicsIGtvKTtcblxuICAgIHNvY2tldC5vbmNlKCdzZWN1cmVDb25uZWN0JywgKCkgPT4ge1xuICAgICAgbGV0IGNlcnQgPSBzb2NrZXQuZ2V0UGVlclg1MDlDZXJ0aWZpY2F0ZSgpO1xuICAgICAgaWYgKCFjZXJ0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIHJldHJpZXZlIFg1MDkgY2VydGlmaWNhdGUgZnJvbSBob3N0ICR7cHVybC5ob3N0fWApO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGNlcnQuaXNzdWVyQ2VydGlmaWNhdGUpIHtcbiAgICAgICAgcHJpbnRDZXJ0aWZpY2F0ZShjZXJ0KTtcbiAgICAgICAgY2VydCA9IGNlcnQuaXNzdWVyQ2VydGlmaWNhdGU7XG4gICAgICB9XG4gICAgICBjb25zdCB2YWxpZFRvID0gbmV3IERhdGUoY2VydC52YWxpZFRvKTtcbiAgICAgIGNvbnN0IGNlcnRpZmljYXRlVmFsaWRpdHkgPSBnZXRDZXJ0aWZpY2F0ZVZhbGlkaXR5KHZhbGlkVG8pO1xuXG4gICAgICBpZiAoY2VydGlmaWNhdGVWYWxpZGl0eSA8IDApIHtcbiAgICAgICAgcmV0dXJuIGtvKG5ldyBFcnJvcihgVGhlIGNlcnRpZmljYXRlIGhhcyBhbHJlYWR5IGV4cGlyZWQgb246ICR7dmFsaWRUby50b1VUQ1N0cmluZygpfWApKTtcbiAgICAgIH1cblxuICAgICAgLy8gV2FybmluZyB1c2VyIGlmIGNlcnRpZmljYXRlIHZhbGlkaXR5IGlzIGV4cGlyaW5nIHdpdGhpbiA2IG1vbnRoc1xuICAgICAgaWYgKGNlcnRpZmljYXRlVmFsaWRpdHkgPCAxODApIHtcbiAgICAgICAgLyogZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUgKi9cbiAgICAgICAgY29uc29sZS53YXJuKGBUaGUgcm9vdCBjZXJ0aWZpY2F0ZSBvYnRhaW5lZCB3b3VsZCBleHBpcmUgaW4gJHtjZXJ0aWZpY2F0ZVZhbGlkaXR5fSBkYXlzIWApO1xuICAgICAgfVxuXG4gICAgICBzb2NrZXQuZW5kKCk7XG5cbiAgICAgIGNvbnN0IHRodW1icHJpbnQgPSBleHRyYWN0VGh1bWJwcmludChjZXJ0KTtcbiAgICAgIGV4dGVybmFsLmxvZyhgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IHRodW1icHJpbnQgZm9yICR7aXNzdWVyVXJsfSBpcyAke3RodW1icHJpbnR9YCk7XG5cbiAgICAgIG9rKHRodW1icHJpbnQpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFRodW1icHJpbnQoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIHJldHVybiBjZXJ0LmZpbmdlcnByaW50LnNwbGl0KCc6Jykuam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIHByaW50Q2VydGlmaWNhdGUoY2VydDogWDUwOUNlcnRpZmljYXRlKSB7XG4gIGV4dGVybmFsLmxvZygnLS0tLS0tLS0tLS0tLUJFR0lOIENFUlQtLS0tLS0tLS0tLS0tLS0tJyk7XG4gIGV4dGVybmFsLmxvZyhgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0KX1gKTtcbiAgZXh0ZXJuYWwubG9nKGBWYWxpZCBUbzogJHtjZXJ0LnZhbGlkVG99YCk7XG4gIGlmIChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKSB7XG4gICAgZXh0ZXJuYWwubG9nKGBJc3N1ZXIgVGh1bWJwcmludDogJHtleHRyYWN0VGh1bWJwcmludChjZXJ0Lmlzc3VlckNlcnRpZmljYXRlKX1gKTtcbiAgfVxuICBleHRlcm5hbC5sb2coYElzc3VlcjogJHtjZXJ0Lmlzc3Vlcn1gKTtcbiAgZXh0ZXJuYWwubG9nKGBTdWJqZWN0OiAke2NlcnQuc3ViamVjdH1gKTtcbiAgZXh0ZXJuYWwubG9nKCctLS0tLS0tLS0tLS0tRU5EIENFUlQtLS0tLS0tLS0tLS0tLS0tLS0nKTtcbn1cblxuLyoqXG4gKiBUbyBnZXQgdGhlIHZhbGlkaXR5IHRpbWVsaW5lIGZvciB0aGUgY2VydGlmaWNhdGVcbiAqIEBwYXJhbSBjZXJ0RGF0ZSBUaGUgdmFsaWQgdG8gZGF0ZSBmb3IgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIGRheXMgdGhlIGNlcnRpZmljYXRlIGlzIHZhbGlkIHdydCBjdXJyZW50IGRhdGVcbiAqL1xuZnVuY3Rpb24gZ2V0Q2VydGlmaWNhdGVWYWxpZGl0eShjZXJ0RGF0ZTogRGF0ZSk6IE51bWJlciB7XG4gIGNvbnN0IG1pbGxpc2Vjb25kc0luRGF5ID0gMjQgKiA2MCAqIDYwICogMTAwMDtcbiAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIGNvbnN0IHZhbGlkaXR5ID0gTWF0aC5yb3VuZCgoY2VydERhdGUuZ2V0VGltZSgpIC0gY3VycmVudERhdGUuZ2V0VGltZSgpKSAvIG1pbGxpc2Vjb25kc0luRGF5KTtcblxuICByZXR1cm4gdmFsaWRpdHk7XG59XG5cbi8vIGFsbG93cyB1bml0IHRlc3QgdG8gcmVwbGFjZSB3aXRoIG1vY2tzXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5leHBvcnQgY29uc3QgZXh0ZXJuYWwgPSB7XG4gIGRvd25sb2FkVGh1bWJwcmludCxcbiAgbG9nOiBkZWZhdWx0TG9nZ2VyLFxuICBjcmVhdGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uQ3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuY3JlYXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICBkZWxldGVPcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uRGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkuZGVsZXRlT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICB1cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50OiAocmVxOiBhd3MuSUFNLlVwZGF0ZU9wZW5JRENvbm5lY3RQcm92aWRlclRodW1icHJpbnRSZXF1ZXN0KSA9PiBpYW0oKS51cGRhdGVPcGVuSURDb25uZWN0UHJvdmlkZXJUaHVtYnByaW50KHJlcSkucHJvbWlzZSgpLFxuICBhZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyOiAocmVxOiBhd3MuSUFNLkFkZENsaWVudElEVG9PcGVuSURDb25uZWN0UHJvdmlkZXJSZXF1ZXN0KSA9PiBpYW0oKS5hZGRDbGllbnRJRFRvT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxuICByZW1vdmVDbGllbnRJREZyb21PcGVuSURDb25uZWN0UHJvdmlkZXI6IChyZXE6IGF3cy5JQU0uUmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyUmVxdWVzdCkgPT4gaWFtKCkucmVtb3ZlQ2xpZW50SURGcm9tT3BlbklEQ29ubmVjdFByb3ZpZGVyKHJlcSkucHJvbWlzZSgpLFxufTsiXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json index 59e0b92f1c992..ecf4e6c5b6949 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.assets.json @@ -1,20 +1,20 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { - "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057": { + "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3": { "source": { - "path": "asset.56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057", + "path": "asset.2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057.zip", + "objectKey": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045": { + "9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41": { "source": { "path": "aws-eks-oidc-provider-test.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045.json", + "objectKey": "9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json index c6e27521470aa..7d51bc35d777e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/aws-eks-oidc-provider-test.template.json @@ -24,7 +24,7 @@ ] ] }, - "CodeHash": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057" + "CodeHash": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -79,7 +79,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "56b85a7bb756e34ab12549549eb40d34151db41531599e8f2be6c04e8ae66057.zip" + "S3Key": "2df5a59d801a1efa337d7f2787d401cc48d736faa94d1f42eccad2d88f3ce2e3.zip" }, "Timeout": 900, "MemorySize": 128, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json index 76c8b566c39da..8b83396d2c274 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/awscdkeksoidcproviderDefaultTestDeployAssert0BFFC9B9.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json index 5ddd0b2dca668..4c5a77e0f9dbe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-oidc-provider/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json index 9330792a2acec..4cb1d3eb3636d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-eks-oidc-provider-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/4e955be736aaca99ba72477fbbb5552c4f27f3b34b7a3879f2654a831127f045.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9c63eb07e389af82f82f1347328d2ed0c1e975c2f142d2be2d55e48d9603ed41.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json index 25fc52ed0d758..65509938458bb 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-oidc-provider.js.snapshot/tree.json @@ -105,7 +105,7 @@ "path": "aws-cdk-eks-oidc-provider/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } }, "DeployAssert": { @@ -151,7 +151,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/index.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json index fd01a578d678a..be236d4d2296a 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -118,7 +118,7 @@ } } }, - "4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583": { + "5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364": { "source": { "path": "awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json", + "objectKey": "5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a": { + "2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb": { "source": { "path": "awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json", "packaging": "file" @@ -139,12 +139,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json", + "objectKey": "2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9": { + "70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d": { "source": { "path": "aws-eks-service-account-sdk-calls-test.template.json", "packaging": "file" @@ -152,7 +152,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9.json", + "objectKey": "70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json index 8dc1162cddda2..c21ba972188e5 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/aws-eks-service-account-sdk-calls-test.template.json @@ -1096,7 +1096,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json" + "/5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json" ] ] }, @@ -1131,7 +1131,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json" + "/2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json index 1c0686d9de199..52b8d483d98d1 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awscdkeksserviceaccountsdkcallDefaultTestDeployAssertC5196707.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json index ef7ce8b1f8fa2..876e30e0f99ff 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksClusterResourceProvider7862DD6A.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json index cd0e765e57a11..2c5bcceca8f1e 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/awseksserviceaccountsdkcallstestawscdkawseksKubectlProvider62B779F7.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json index 7568669a378e9..c51334d485b28 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-service-account-sdk-call/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json index 4737b9e88162e..39ef825a5901b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-eks-service-account-sdk-calls-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/3ba669b8cbb8100db0bc3a91c65b4b388c7b96bfe1a594706161a256fc9500f9.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/70966cef1197eaa250138ee97adb33cc0a849cfd8074fb47480dd7db4bcc4f4d.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json index 211767771b8a2..7082a77fa70aa 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.eks-service-account-sdk-call.js.snapshot/tree.json @@ -1624,7 +1624,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1797,7 +1797,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2695,7 +2695,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/4422b5163ce3c03b7df4cc3c0f3ab30647ac2ac54fad5e3e1cb022b6d377a583.json" + "/5a9c925516063e7d602e462f9d785c5c8918c64f4f3d1fda0b413dfb1dd87364.json" ] ] }, @@ -2794,6 +2794,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2893,7 +2905,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "e8df8261cf82310642e2ba891e96133429f5e7dcba09fa805f4c82818d0c3bb9.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3363,7 +3375,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/56a93a19ca9db980b01dbf3dbea01632e423c2529b92baa1cbd4c650df41b83a.json" + "/2add9700d3e45c3801eaf35070c27d935901edd64bf8e1bd2ddbdde470263bdb.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py deleted file mode 100644 index b9a741c8972c4..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/helm/__init__.py +++ /dev/null @@ -1,187 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['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) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/common.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/fargate.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.d.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/index.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 593043af0139a..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js deleted file mode 100644 index 6efe7fd22e321..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.js +++ /dev/null @@ -1,267 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size || [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LElBQUksS0FBSyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBJc0NvbXBsZXRlUmVzcG9uc2UsIE9uRXZlbnRSZXNwb25zZSB9IGZyb20gJ0Bhd3MtY2RrL2N1c3RvbS1yZXNvdXJjZXMvbGliL3Byb3ZpZGVyLWZyYW1ld29yay90eXBlcyc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7XG5pbXBvcnQgeyBFa3NDbGllbnQsIFJlc291cmNlRXZlbnQsIFJlc291cmNlSGFuZGxlciB9IGZyb20gJy4vY29tbW9uJztcblxuY29uc3QgTUFYX0NMVVNURVJfTkFNRV9MRU4gPSAxMDA7XG5cbmV4cG9ydCBjbGFzcyBDbHVzdGVyUmVzb3VyY2VIYW5kbGVyIGV4dGVuZHMgUmVzb3VyY2VIYW5kbGVyIHtcbiAgcHVibGljIGdldCBjbHVzdGVyTmFtZSgpIHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBkZXRlcm1pbmUgY2x1c3RlciBuYW1lIHdpdGhvdXQgcGh5c2ljYWwgcmVzb3VyY2UgSUQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5waHlzaWNhbFJlc291cmNlSWQ7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG5ld1Byb3BzOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0O1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+O1xuXG4gIGNvbnN0cnVjdG9yKGVrczogRWtzQ2xpZW50LCBldmVudDogUmVzb3VyY2VFdmVudCkge1xuICAgIHN1cGVyKGVrcywgZXZlbnQpO1xuXG4gICAgdGhpcy5uZXdQcm9wcyA9IHBhcnNlUHJvcHModGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMpO1xuICAgIHRoaXMub2xkUHJvcHMgPSBldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ1VwZGF0ZScgPyBwYXJzZVByb3BzKGV2ZW50Lk9sZFJlc291cmNlUHJvcGVydGllcykgOiB7fTtcbiAgfVxuXG4gIC8vIC0tLS0tLVxuICAvLyBDUkVBVEVcbiAgLy8gLS0tLS0tXG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uQ3JlYXRlKCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coJ29uQ3JlYXRlOiBjcmVhdGluZyBjbHVzdGVyIHdpdGggb3B0aW9uczonLCBKU09OLnN0cmluZ2lmeSh0aGlzLm5ld1Byb3BzLCB1bmRlZmluZWQsIDIpKTtcbiAgICBpZiAoIXRoaXMubmV3UHJvcHMucm9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcInJvbGVBcm5cIiBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gdGhpcy5uZXdQcm9wcy5uYW1lIHx8IHRoaXMuZ2VuZXJhdGVDbHVzdGVyTmFtZSgpO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmNyZWF0ZUNsdXN0ZXIoe1xuICAgICAgLi4udGhpcy5uZXdQcm9wcyxcbiAgICAgIG5hbWU6IGNsdXN0ZXJOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwLmNsdXN0ZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Igd2hlbiB0cnlpbmcgdG8gY3JlYXRlIGNsdXN0ZXIgJHtjbHVzdGVyTmFtZX06IENyZWF0ZUNsdXN0ZXIgcmV0dXJuZWQgd2l0aG91dCBjbHVzdGVyIGluZm9ybWF0aW9uYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcmVzcC5jbHVzdGVyLm5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gREVMRVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKGBvbkRlbGV0ZTogZGVsZXRpbmcgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUNsdXN0ZXIoeyBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgIT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSBub3QgZm91bmQsIGlkZW1wb3RlbnRseSBzdWNjZWVkZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgaXNEZWxldGVDb21wbGV0ZTogd2FpdGluZyBmb3IgY2x1c3RlciAke3RoaXMuY2x1c3Rlck5hbWV9IHRvIGJlIGRlbGV0ZWRgKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgcmV0dXJuZWQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKGUuY29kZSA9PT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdyZWNlaXZlZCBSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uLCB0aGlzIG1lYW5zIHRoZSBjbHVzdGVyIGhhcyBiZWVuIGRlbGV0ZWQgKG9yIG5ldmVyIGV4aXN0ZWQpJyk7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciBlcnJvcjonLCBlKTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgIH07XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gVVBEQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvblVwZGF0ZSgpIHtcbiAgICBjb25zdCB1cGRhdGVzID0gYW5hbHl6ZVVwZGF0ZSh0aGlzLm9sZFByb3BzLCB0aGlzLm5ld1Byb3BzKTtcbiAgICBjb25zb2xlLmxvZygnb25VcGRhdGU6JywgSlNPTi5zdHJpbmdpZnkoeyB1cGRhdGVzIH0sIHVuZGVmaW5lZCwgMikpO1xuXG4gICAgLy8gdXBkYXRlcyB0byBlbmNyeXB0aW9uIGNvbmZpZyBpcyBub3Qgc3VwcG9ydGVkXG4gICAgaWYgKHVwZGF0ZXMudXBkYXRlRW5jcnlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXBkYXRlIGNsdXN0ZXIgZW5jcnlwdGlvbiBjb25maWd1cmF0aW9uJyk7XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgaXMgYW4gdXBkYXRlIHRoYXQgcmVxdWlyZXMgcmVwbGFjZW1lbnQsIGdvIGFoZWFkIGFuZCBqdXN0IGNyZWF0ZVxuICAgIC8vIGEgbmV3IGNsdXN0ZXIgd2l0aCB0aGUgbmV3IGNvbmZpZy4gVGhlIG9sZCBjbHVzdGVyIHdpbGwgYXV0b21hdGljYWxseSBiZVxuICAgIC8vIGRlbGV0ZWQgYnkgY2xvdWRmb3JtYXRpb24gdXBvbiBzdWNjZXNzLlxuICAgIGlmICh1cGRhdGVzLnJlcGxhY2VOYW1lIHx8IHVwZGF0ZXMucmVwbGFjZVJvbGUgfHwgdXBkYXRlcy5yZXBsYWNlVnBjKSB7XG5cbiAgICAgIC8vIGlmIHdlIGFyZSByZXBsYWNpbmcgdGhpcyBjbHVzdGVyIGFuZCB0aGUgY2x1c3RlciBoYXMgYW4gZXhwbGljaXRcbiAgICAgIC8vIHBoeXNpY2FsIG5hbWUsIHRoZSBjcmVhdGlvbiBvZiB0aGUgbmV3IGNsdXN0ZXIgd2lsbCBmYWlsIHdpdGggXCJ0aGVyZSBpc1xuICAgICAgLy8gYWxyZWFkeSBhIGNsdXN0ZXIgd2l0aCB0aGF0IG5hbWVcIi4gdGhpcyBpcyBhIGNvbW1vbiBiZWhhdmlvciBmb3JcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uIHJlc291cmNlcyB0aGF0IHN1cHBvcnQgc3BlY2lmeWluZyBhIHBoeXNpY2FsIG5hbWUuXG4gICAgICBpZiAodGhpcy5vbGRQcm9wcy5uYW1lID09PSB0aGlzLm5ld1Byb3BzLm5hbWUgJiYgdGhpcy5vbGRQcm9wcy5uYW1lKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlcGxhY2UgY2x1c3RlciBcIiR7dGhpcy5vbGRQcm9wcy5uYW1lfVwiIHNpbmNlIGl0IGhhcyBhbiBleHBsaWNpdCBwaHlzaWNhbCBuYW1lLiBFaXRoZXIgcmVuYW1lIHRoZSBjbHVzdGVyIG9yIHJlbW92ZSB0aGUgXCJuYW1lXCIgY29uZmlndXJhdGlvbmApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgIH1cblxuICAgIC8vIGlmIGEgdmVyc2lvbiB1cGRhdGUgaXMgcmVxdWlyZWQsIGlzc3VlIHRoZSB2ZXJzaW9uIHVwZGF0ZVxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZVZlcnNpb24pIHtcbiAgICAgIGlmICghdGhpcy5uZXdQcm9wcy52ZXJzaW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlbW92ZSBjbHVzdGVyIHZlcnNpb24gY29uZmlndXJhdGlvbi4gQ3VycmVudCB2ZXJzaW9uIGlzICR7dGhpcy5vbGRQcm9wcy52ZXJzaW9ufWApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy51cGRhdGVDbHVzdGVyVmVyc2lvbih0aGlzLm5ld1Byb3BzLnZlcnNpb24pO1xuICAgIH1cblxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUxvZ2dpbmcgfHwgdXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgIGNvbnN0IGNvbmZpZzogYXdzLkVLUy5VcGRhdGVDbHVzdGVyQ29uZmlnUmVxdWVzdCA9IHtcbiAgICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgICAgbG9nZ2luZzogdGhpcy5uZXdQcm9wcy5sb2dnaW5nLFxuICAgICAgfTtcbiAgICAgIGlmICh1cGRhdGVzLnVwZGF0ZUFjY2Vzcykge1xuICAgICAgICAvLyBVcGRhdGluZyB0aGUgY2x1c3RlciB3aXRoIHNlY3VyaXR5R3JvdXBJZHMgYW5kIHN1Ym5ldElkcyAoYXMgc3BlY2lmaWVkIGluIHRoZSB3YXJuaW5nIGhlcmU6XG4gICAgICAgIC8vIGh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vdjIvZG9jdW1lbnRhdGlvbi9hcGkvbGF0ZXN0L3JlZmVyZW5jZS9la3MvdXBkYXRlLWNsdXN0ZXItY29uZmlnLmh0bWwpXG4gICAgICAgIC8vIHdpbGwgZmFpbCwgdGhlcmVmb3JlIHdlIHRha2Ugb25seSB0aGUgYWNjZXNzIGZpZWxkcyBleHBsaWNpdGx5XG4gICAgICAgIGNvbmZpZy5yZXNvdXJjZXNWcGNDb25maWcgPSB7XG4gICAgICAgICAgZW5kcG9pbnRQcml2YXRlQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MsXG4gICAgICAgICAgZW5kcG9pbnRQdWJsaWNBY2Nlc3M6IHRoaXMubmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzLFxuICAgICAgICAgIHB1YmxpY0FjY2Vzc0NpZHJzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5wdWJsaWNBY2Nlc3NDaWRycyxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MudXBkYXRlQ2x1c3RlckNvbmZpZyhjb25maWcpO1xuXG4gICAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICAgIH1cblxuICAgIC8vIG5vIHVwZGF0ZXNcbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zb2xlLmxvZygnaXNVcGRhdGVDb21wbGV0ZScpO1xuXG4gICAgLy8gaWYgdGhpcyBpcyBhbiBFS1MgdXBkYXRlLCB3ZSB3aWxsIG1vbml0b3IgdGhlIHVwZGF0ZSBldmVudCBpdHNlbGZcbiAgICBpZiAodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCkge1xuICAgICAgY29uc3QgY29tcGxldGUgPSBhd2FpdCB0aGlzLmlzRWtzVXBkYXRlQ29tcGxldGUodGhpcy5ldmVudC5Fa3NVcGRhdGVJZCk7XG4gICAgICBpZiAoIWNvbXBsZXRlKSB7XG4gICAgICAgIHJldHVybiB7IElzQ29tcGxldGU6IGZhbHNlIH07XG4gICAgICB9XG5cbiAgICAgIC8vIGZhbGwgdGhyb3VnaDogaWYgdGhlIHVwZGF0ZSBpcyBkb25lLCB3ZSBzaW1wbHkgZGVsZWdhdGUgdG8gaXNBY3RpdmUoKVxuICAgICAgLy8gaW4gb3JkZXIgdG8gZXh0cmFjdCBhdHRyaWJ1dGVzIGFuZCBzdGF0ZSBmcm9tIHRoZSBjbHVzdGVyIGl0c2VsZiwgd2hpY2hcbiAgICAgIC8vIGlzIHN1cHBvc2VkIHRvIGJlIGluIGFuIEFDVElWRSBzdGF0ZSBhZnRlciB0aGUgdXBkYXRlIGlzIGNvbXBsZXRlLlxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmlzQWN0aXZlKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKG5ld1ZlcnNpb246IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKGB1cGRhdGluZyBjbHVzdGVyIHZlcnNpb24gdG8gJHtuZXdWZXJzaW9ufWApO1xuXG4gICAgLy8gdXBkYXRlLWNsdXN0ZXItdmVyc2lvbiB3aWxsIGZhaWwgaWYgd2UgdHJ5IHRvIHVwZGF0ZSB0byB0aGUgc2FtZSB2ZXJzaW9uLFxuICAgIC8vIHNvIHNraXAgaW4gdGhpcyBjYXNlLlxuICAgIGNvbnN0IGNsdXN0ZXIgPSAoYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSkuY2x1c3RlcjtcbiAgICBpZiAoY2x1c3Rlcj8udmVyc2lvbiA9PT0gbmV3VmVyc2lvbikge1xuICAgICAgY29uc29sZS5sb2coYGNsdXN0ZXIgYWxyZWFkeSBhdCB2ZXJzaW9uICR7Y2x1c3Rlci52ZXJzaW9ufSwgc2tpcHBpbmcgdmVyc2lvbiB1cGRhdGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSwgdmVyc2lvbjogbmV3VmVyc2lvbiB9KTtcbiAgICByZXR1cm4geyBFa3NVcGRhdGVJZDogdXBkYXRlUmVzcG9uc2UudXBkYXRlPy5pZCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpc0FjdGl2ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCd3YWl0aW5nIGZvciBjbHVzdGVyIHRvIGJlY29tZSBBQ1RJVkUnKTtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJlc3VsdDonLCBKU09OLnN0cmluZ2lmeShyZXNwLCB1bmRlZmluZWQsIDIpKTtcbiAgICBjb25zdCBjbHVzdGVyID0gcmVzcC5jbHVzdGVyO1xuXG4gICAgLy8gaWYgY2x1c3RlciBpcyB1bmRlZmluZWQgKHNob3VsZG50IGhhcHBlbikgb3Igc3RhdHVzIGlzIG5vdCBBQ1RJVkUsIHdlIGFyZVxuICAgIC8vIG5vdCBjb21wbGV0ZS4gbm90ZSB0aGF0IHRoZSBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgZnJhbWV3b3JrIGZvcmJpZHNcbiAgICAvLyByZXR1cm5pbmcgYXR0cmlidXRlcyAoRGF0YSkgaWYgaXNDb21wbGV0ZSBpcyBmYWxzZS5cbiAgICBpZiAoY2x1c3Rlcj8uc3RhdHVzID09PSAnRkFJTEVEJykge1xuICAgICAgLy8gbm90IHZlcnkgaW5mb3JtYXRpdmUsIHVuZm9ydHVuYXRlbHkgdGhlIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpbiBhbnkgZXJyb3JcbiAgICAgIC8vIGluZm9ybWF0aW9uIDpcXFxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDbHVzdGVyIGlzIGluIGEgRkFJTEVEIHN0YXR1cycpO1xuICAgIH0gZWxzZSBpZiAoY2x1c3Rlcj8uc3RhdHVzICE9PSAnQUNUSVZFJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogZmFsc2UsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBJc0NvbXBsZXRlOiB0cnVlLFxuICAgICAgICBEYXRhOiB7XG4gICAgICAgICAgTmFtZTogY2x1c3Rlci5uYW1lLFxuICAgICAgICAgIEVuZHBvaW50OiBjbHVzdGVyLmVuZHBvaW50LFxuICAgICAgICAgIEFybjogY2x1c3Rlci5hcm4sXG5cbiAgICAgICAgICAvLyBJTVBPUlRBTlQ6IENGTiBleHBlY3RzIHRoYXQgYXR0cmlidXRlcyB3aWxsICphbHdheXMqIGhhdmUgdmFsdWVzLFxuICAgICAgICAgIC8vIHNvIHJldHVybiBhbiBlbXB0eSBzdHJpbmcgaW4gY2FzZSB0aGUgdmFsdWUgaXMgbm90IGRlZmluZWQuXG4gICAgICAgICAgLy8gT3RoZXJ3aXNlLCBDRk4gd2lsbCB0aHJvdyB3aXRoIGBWZW5kb3IgcmVzcG9uc2UgZG9lc24ndCBjb250YWluXG4gICAgICAgICAgLy8gWFhYWCBrZXlgLlxuXG4gICAgICAgICAgQ2VydGlmaWNhdGVBdXRob3JpdHlEYXRhOiBjbHVzdGVyLmNlcnRpZmljYXRlQXV0aG9yaXR5Py5kYXRhID8/ICcnLFxuICAgICAgICAgIENsdXN0ZXJTZWN1cml0eUdyb3VwSWQ6IGNsdXN0ZXIucmVzb3VyY2VzVnBjQ29uZmlnPy5jbHVzdGVyU2VjdXJpdHlHcm91cElkID8/ICcnLFxuICAgICAgICAgIE9wZW5JZENvbm5lY3RJc3N1ZXJVcmw6IGNsdXN0ZXIuaWRlbnRpdHk/Lm9pZGM/Lmlzc3VlciA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXI/LnN1YnN0cmluZyg4KSA/PyAnJywgLy8gU3RyaXBzIG9mZiBodHRwczovLyBmcm9tIHRoZSBpc3N1ZXIgdXJsXG5cbiAgICAgICAgICAvLyBXZSBjYW4gc2FmZWx5IHJldHVybiB0aGUgZmlyc3QgaXRlbSBmcm9tIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiBhcnJheSwgYmVjYXVzZSBpdCBoYXMgYSBsaW1pdCBvZiAxIGl0ZW1cbiAgICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZWtzL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUNsdXN0ZXIuaHRtbCNBbWF6b25FS1MtQ3JlYXRlQ2x1c3Rlci1yZXF1ZXN0LWVuY3J5cHRpb25Db25maWdcbiAgICAgICAgICBFbmNyeXB0aW9uQ29uZmlnS2V5QXJuOiBjbHVzdGVyLmVuY3J5cHRpb25Db25maWc/LnNoaWZ0KCk/LnByb3ZpZGVyPy5rZXlBcm4gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNFa3NVcGRhdGVDb21wbGV0ZShla3NVcGRhdGVJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5sb2coeyBpc0Vrc1VwZGF0ZUNvbXBsZXRlOiBla3NVcGRhdGVJZCB9KTtcblxuICAgIGNvbnN0IGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy5kZXNjcmliZVVwZGF0ZSh7XG4gICAgICBuYW1lOiB0aGlzLmNsdXN0ZXJOYW1lLFxuICAgICAgdXBkYXRlSWQ6IGVrc1VwZGF0ZUlkLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sb2coeyBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlIH0pO1xuXG4gICAgaWYgKCFkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmFibGUgdG8gZGVzY3JpYmUgdXBkYXRlIHdpdGggaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXMpIHtcbiAgICAgIGNhc2UgJ0luUHJvZ3Jlc3MnOlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICBjYXNlICdTdWNjZXNzZnVsJzpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICBjYXNlICdGYWlsZWQnOlxuICAgICAgY2FzZSAnQ2FuY2VsbGVkJzpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjbHVzdGVyIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCIgZmFpbGVkIHdpdGggZXJyb3JzOiAke0pTT04uc3RyaW5naWZ5KGRlc2NyaWJlVXBkYXRlUmVzcG9uc2UudXBkYXRlLmVycm9ycyl9YCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gc3RhdHVzIFwiJHtkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5zdGF0dXN9XCIgZm9yIHVwZGF0ZSBpZCBcIiR7ZWtzVXBkYXRlSWR9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlQ2x1c3Rlck5hbWUoKSB7XG4gICAgY29uc3Qgc3VmZml4ID0gdGhpcy5yZXF1ZXN0SWQucmVwbGFjZSgvLS9nLCAnJyk7IC8vIDMyIGNoYXJzXG4gICAgY29uc3Qgb2Zmc2V0ID0gTUFYX0NMVVNURVJfTkFNRV9MRU4gLSBzdWZmaXgubGVuZ3RoIC0gMTtcbiAgICBjb25zdCBwcmVmaXggPSB0aGlzLmxvZ2ljYWxSZXNvdXJjZUlkLnNsaWNlKDAsIG9mZnNldCA+IDAgPyBvZmZzZXQgOiAwKTtcbiAgICByZXR1cm4gYCR7cHJlZml4fS0ke3N1ZmZpeH1gO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhcnNlUHJvcHMocHJvcHM6IGFueSk6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Qge1xuXG4gIGNvbnN0IHBhcnNlZCA9IHByb3BzPy5Db25maWcgPz8ge307XG5cbiAgLy8gdGhpcyBpcyB3ZWlyZCBidXQgdGhlc2UgYm9vbGVhbiBwcm9wZXJ0aWVzIGFyZSBwYXNzZWQgYnkgQ0ZOIGFzIGEgc3RyaW5nLCBhbmQgd2UgbmVlZCB0aGVtIHRvIGJlIGJvb2xlYW5pYyBmb3IgdGhlIFNESy5cbiAgLy8gT3RoZXJ3aXNlIGl0IGZhaWxzIHdpdGggJ1VuZXhwZWN0ZWQgUGFyYW1ldGVyOiBwYXJhbXMucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBpcyBleHBlY3RlZCB0byBiZSBhIGJvb2xlYW4nXG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQcml2YXRlQWNjZXNzKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnPy5lbmRwb2ludFB1YmxpY0FjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyA9IHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPT09ICd0cnVlJztcbiAgfVxuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5sb2dnaW5nPy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkKSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJzZWQubG9nZ2luZy5jbHVzdGVyTG9nZ2luZ1swXS5lbmFibGVkID0gcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9PT0gJ3RydWUnO1xuICB9XG5cbiAgcmV0dXJuIHBhcnNlZDtcblxufVxuXG5pbnRlcmZhY2UgVXBkYXRlTWFwIHtcbiAgcmVwbGFjZU5hbWU6IGJvb2xlYW47IC8vIG5hbWVcbiAgcmVwbGFjZVZwYzogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLnN1Ym5ldElkcyBhbmQgc2VjdXJpdHlHcm91cElkc1xuICByZXBsYWNlUm9sZTogYm9vbGVhbjsgLy8gcm9sZUFyblxuXG4gIHVwZGF0ZVZlcnNpb246IGJvb2xlYW47IC8vIHZlcnNpb25cbiAgdXBkYXRlTG9nZ2luZzogYm9vbGVhbjsgLy8gbG9nZ2luZ1xuICB1cGRhdGVFbmNyeXB0aW9uOiBib29sZWFuOyAvLyBlbmNyeXB0aW9uIChjYW5ub3QgYmUgdXBkYXRlZClcbiAgdXBkYXRlQWNjZXNzOiBib29sZWFuOyAvLyByZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzIGFuZCBlbmRwb2ludFB1YmxpY0FjY2Vzc1xufVxuXG5mdW5jdGlvbiBhbmFseXplVXBkYXRlKG9sZFByb3BzOiBQYXJ0aWFsPGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3Q+LCBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdCk6IFVwZGF0ZU1hcCB7XG4gIGNvbnNvbGUubG9nKCdvbGQgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG9sZFByb3BzKSk7XG4gIGNvbnNvbGUubG9nKCduZXcgcHJvcHM6ICcsIEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzKSk7XG5cbiAgY29uc3QgbmV3VnBjUHJvcHMgPSBuZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcgfHwge307XG4gIGNvbnN0IG9sZFZwY1Byb3BzID0gb2xkUHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuXG4gIGNvbnN0IG9sZFB1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChvbGRWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld1B1YmxpY0FjY2Vzc0NpZHJzID0gbmV3IFNldChuZXdWcGNQcm9wcy5wdWJsaWNBY2Nlc3NDaWRycyA/PyBbXSk7XG4gIGNvbnN0IG5ld0VuYyA9IG5ld1Byb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG4gIGNvbnN0IG9sZEVuYyA9IG9sZFByb3BzLmVuY3J5cHRpb25Db25maWcgfHwge307XG5cbiAgcmV0dXJuIHtcbiAgICByZXBsYWNlTmFtZTogbmV3UHJvcHMubmFtZSAhPT0gb2xkUHJvcHMubmFtZSxcbiAgICByZXBsYWNlVnBjOlxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc3VibmV0SWRzKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzKSB8fFxuICAgICAgSlNPTi5zdHJpbmdpZnkobmV3VnBjUHJvcHMuc2VjdXJpdHlHcm91cElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSB8fCBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts deleted file mode 100644 index 0177a7e21b695..0000000000000 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517/cluster.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - logging: this.newProps.logging, - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size || [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index b64a5034e3b6c..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/apply/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/get/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/index.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33/patch/__init__.py rename to packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip index a0efa36e0518a..9bf8ba72b34ab 100644 Binary files a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip and b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/asset.c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064.zip differ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json index 93e52d0689d1e..b82f69d938a97 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "c475180f5b1bbabac165414da13a9b843b111cd3b6d5fae9c954c006640c4064": { "source": { @@ -27,41 +27,41 @@ } } }, - "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec": { + "4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5": { "source": { "path": "awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json", + "objectKey": "4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325": { + "eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500": { "source": { "path": "awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json", + "objectKey": "eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1": { + "bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13": { "source": { "path": "aws-cdk-eks-fargate-cluster-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1.json", + "objectKey": "bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json index 0410cc141806d..0a3262e1baea9 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/aws-cdk-eks-fargate-cluster-test.template.json @@ -955,7 +955,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json" + "/4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json" ] ] }, @@ -990,7 +990,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json" + "/eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json" ] ] }, diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json index 51ebbd84cea21..430c3c299b42c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclusterDefaultTestDeployAssert7DCC5E4C.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json index 7342c5874547f..fe85dcb4f6e7b 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksClusterResourceProviderB8887E20.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -297,7 +297,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -434,7 +434,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -568,7 +568,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json index 6e77724b99300..6ac42c273fb7d 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/awscdkeksfargateclustertestawscdkawseksKubectlProviderB383571D.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ @@ -238,7 +250,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json index 18e56a84bcf2b..3e6fa6d1ded11 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "aws-cdk-eks-fargate-cluster/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json index 72cdaccd7c7b6..8263237c819fe 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-eks-fargate-cluster-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/9f01c63a68719a7917d90c32f619415229f7cbaca2a55ae8ff985e37f653fdc1.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bcf75f6fbd774fe312af7535b5f3d78609738a015df48e8cbfb4572802108f13.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -36,10 +36,7 @@ "/aws-cdk-eks-fargate-cluster-test/KubectlLayer/Resource": [ { "type": "aws:cdk:logicalId", - "data": "KubectlLayer600207B5", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "KubectlLayer600207B5" } ], "/aws-cdk-eks-fargate-cluster-test/FargateCluster/DefaultVpc/Resource": [ diff --git a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json index b1ce4199b8fc5..3f268f54211b2 100644 --- a/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-eks/test/integ.fargate-cluster.js.snapshot/tree.json @@ -62,7 +62,7 @@ }, "constructInfo": { "fqn": "@aws-cdk/lambda-layer-kubectl-v24.KubectlV24Layer", - "version": "2.0.27" + "version": "2.0.100" } }, "FargateCluster": { @@ -1025,7 +1025,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1473,7 +1473,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1646,7 +1646,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "73edfa4462023915a2f13bf570acae05c5111817c606f9837f832152920ba517.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1869,7 +1869,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2090,7 +2090,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2308,7 +2308,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -2487,7 +2487,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, @@ -2544,7 +2544,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/fc71d3f52bbfd7601c262c027d9b9a1dad423a29a0113574840703d2dec76aec.json" + "/4d43e74130fa986d0dccce8d2b755a1bb2195fe9bf5e8a5531ad69bbb97acaa5.json" ] ] }, @@ -2566,7 +2566,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2643,6 +2643,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2742,7 +2754,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "1f175bea1cef6137d882d0090f49e27e44bbb46a678a86fd5d6fb29ade070a33.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3020,7 +3032,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -3164,7 +3176,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/47ef31ad4e6f7cee2b0651e66eaa0896ec32f1fbbfca379fcea6afc0723d9325.json" + "/eb2424de0291785175d9304f682a14024fef1cdabfc3246c96a6fcdebcc69500.json" ] ] }, @@ -3207,7 +3219,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3245,7 +3257,7 @@ "path": "aws-cdk-eks-fargate-cluster/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } }, "DeployAssert": { @@ -3291,7 +3303,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-eks/test/sdk-call-integ-test-docker-app/app/package.json b/packages/@aws-cdk/aws-eks/test/sdk-call-integ-test-docker-app/app/package.json index e8c7bde1b56a1..e954bcb2b77e7 100644 --- a/packages/@aws-cdk/aws-eks/test/sdk-call-integ-test-docker-app/app/package.json +++ b/packages/@aws-cdk/aws-eks/test/sdk-call-integ-test-docker-app/app/package.json @@ -2,6 +2,6 @@ "name": "eks-service-account-sdk-call-integ-test", "private": "true", "dependencies": { - "aws-sdk": "^2.1313.0" + "aws-sdk": "^2.1325.0" } } diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index 552362b73046c..3455b64b3521f 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -89,7 +89,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-events/test/integ.archive.ts b/packages/@aws-cdk/aws-events/test/integ.archive.ts index b9a47ba6fafe6..2751a8be94502 100644 --- a/packages/@aws-cdk/aws-events/test/integ.archive.ts +++ b/packages/@aws-cdk/aws-events/test/integ.archive.ts @@ -19,5 +19,3 @@ const archive = new Archive(stack, 'Archive', { new IntegTest(app, 'ArchiveTest', { testCases: [stack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-events/test/integ.connection.ts b/packages/@aws-cdk/aws-events/test/integ.connection.ts index 8c000a2e50d75..41df8a9e97f91 100644 --- a/packages/@aws-cdk/aws-events/test/integ.connection.ts +++ b/packages/@aws-cdk/aws-events/test/integ.connection.ts @@ -37,5 +37,3 @@ deployedConncention.expect(ExpectedResult.objectLike({ const assertionProvider = deployedConncention.node.tryFindChild('SdkProvider') as AssertionsProvider; assertionProvider.addPolicyStatementFromSdkCall('events', 'DescribeConnection'); - -app.synth(); diff --git a/packages/@aws-cdk/aws-events/test/integ.cross-account-rule.ts b/packages/@aws-cdk/aws-events/test/integ.cross-account-rule.ts index c77813f90ed56..5578fc2956507 100644 --- a/packages/@aws-cdk/aws-events/test/integ.cross-account-rule.ts +++ b/packages/@aws-cdk/aws-events/test/integ.cross-account-rule.ts @@ -95,5 +95,3 @@ eventVerification.assertAtPath('Policy', ExpectedResult.objectLike({ })], ), })); - -app.synth(); diff --git a/packages/@aws-cdk/aws-events/test/integ.eventbus.ts b/packages/@aws-cdk/aws-events/test/integ.eventbus.ts index 1f3ed2046df6d..79bf046bdde11 100644 --- a/packages/@aws-cdk/aws-events/test/integ.eventbus.ts +++ b/packages/@aws-cdk/aws-events/test/integ.eventbus.ts @@ -22,5 +22,3 @@ bus.addToResourcePolicy(new iam.PolicyStatement({ new IntegTest(app, 'IntegTest-BatchDefaultEnvVarsStack', { testCases: [stack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-events/test/integ.rule.ts b/packages/@aws-cdk/aws-events/test/integ.rule.ts index 9f84ae6e8e398..8b641a5711de1 100644 --- a/packages/@aws-cdk/aws-events/test/integ.rule.ts +++ b/packages/@aws-cdk/aws-events/test/integ.rule.ts @@ -45,5 +45,3 @@ new Rule(stack, 'MyRule', { new IntegTest(app, 'IntegTest-BatchDefaultEnvVarsStack', { testCases: [stack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/GameServerGroupDefaultTestDeployAssertA631B19B.assets.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/GameServerGroupDefaultTestDeployAssertA631B19B.assets.json index f7fa24e781380..91ef9038e0724 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/GameServerGroupDefaultTestDeployAssertA631B19B.assets.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/GameServerGroupDefaultTestDeployAssertA631B19B.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.assets.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.assets.json index 5d2d42f94c1eb..3d77e4130511e 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.assets.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { - "0233f946355da9a29bd7caaf5049caf4cd4e71dfa10d084bd5ff56e547903847": { + "aea05f75441842463319434840166da7e1c6156dbb321d52b22c5ec2174adfc2": { "source": { "path": "aws-gamelift-game-server-group.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "0233f946355da9a29bd7caaf5049caf4cd4e71dfa10d084bd5ff56e547903847.json", + "objectKey": "aea05f75441842463319434840166da7e1c6156dbb321d52b22c5ec2174adfc2.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.template.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.template.json index 451002608b0dc..85efe09357b4f 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.template.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/aws-gamelift-game-server-group.template.json @@ -417,7 +417,10 @@ } ] } - ] + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } }, "TagSpecifications": [ { diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/cdk.out b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/cdk.out index 8ecc185e9dbee..145739f539580 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/integ.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/integ.json index 7dfb7ecf345df..cae6781e9e083 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "22.0.0", "testCases": { "GameServerGroup/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/manifest.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/manifest.json index 97bde0478466e..3dcafd41299d3 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-gamelift-game-server-group.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/0233f946355da9a29bd7caaf5049caf4cd4e71dfa10d084bd5ff56e547903847.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/aea05f75441842463319434840166da7e1c6156dbb321d52b22c5ec2174adfc2.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -262,6 +256,12 @@ ] }, "displayName": "GameServerGroup/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/tree.json b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/tree.json index 486d29aa67194..eaab485b51630 100644 --- a/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-gamelift/test/integ.game-server-group.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.140" - } - }, "aws-gamelift-game-server-group": { "id": "aws-gamelift-game-server-group", "path": "aws-gamelift-game-server-group", @@ -692,7 +684,10 @@ } ] } - ] + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } }, "tagSpecifications": [ { @@ -742,6 +737,14 @@ "id": "ServiceRole", "path": "aws-gamelift-game-server-group/MyGameServerGroup/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-gamelift-game-server-group/MyGameServerGroup/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-gamelift-game-server-group/MyGameServerGroup/ServiceRole/Resource", @@ -846,6 +849,22 @@ "fqn": "@aws-cdk/aws-gamelift.GameServerGroup", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-gamelift-game-server-group/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-gamelift-game-server-group/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { @@ -866,12 +885,30 @@ "path": "GameServerGroup/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.189" } }, "DeployAssert": { "id": "DeployAssert", "path": "GameServerGroup/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "GameServerGroup/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "GameServerGroup/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" @@ -888,6 +925,14 @@ "fqn": "@aws-cdk/integ-tests.IntegTest", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json b/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json index 2a9c7bac3b8e6..2f1f657b94807 100644 --- a/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json +++ b/packages/@aws-cdk/aws-globalaccelerator-endpoints/package.json @@ -81,7 +81,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-iam/lib/group.ts b/packages/@aws-cdk/aws-iam/lib/group.ts index 0b81c6c572158..850c9a4a660d1 100644 --- a/packages/@aws-cdk/aws-iam/lib/group.ts +++ b/packages/@aws-cdk/aws-iam/lib/group.ts @@ -1,4 +1,4 @@ -import { ArnFormat, Lazy, Resource, Stack } from '@aws-cdk/core'; +import { Annotations, ArnFormat, Lazy, Resource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnGroup } from './iam.generated'; import { IIdentity } from './identity-base'; @@ -200,14 +200,25 @@ export class Group extends GroupBase { // Removes leading slash from path resourceName: `${props.path ? props.path.substr(props.path.charAt(0) === '/' ? 1 : 0) : ''}${this.physicalName}`, }); + + this.managedPoliciesExceededWarning(); } /** - * Attaches a managed policy to this group. + * Attaches a managed policy to this group. See [IAM and AWS STS quotas, name requirements, and character limits] + * (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-quotas-entities) + * for quota of managed policies attached to an IAM group. * @param policy The managed policy to attach. */ public addManagedPolicy(policy: IManagedPolicy) { if (this.managedPolicies.find(mp => mp === policy)) { return; } this.managedPolicies.push(policy); + this.managedPoliciesExceededWarning(); + } + + private managedPoliciesExceededWarning() { + if (this.managedPolicies.length > 10) { + Annotations.of(this).addWarning(`You added ${this.managedPolicies.length} to IAM Group ${this.physicalName}. The maximum number of managed policies attached to an IAM group is 10.`); + } } } diff --git a/packages/@aws-cdk/aws-iam/package.json b/packages/@aws-cdk/aws-iam/package.json index f42f7619e20d2..22800ec1f5fad 100644 --- a/packages/@aws-cdk/aws-iam/package.json +++ b/packages/@aws-cdk/aws-iam/package.json @@ -86,7 +86,7 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "@types/sinon": "^9.0.11", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/aws-iam/test/group.test.ts b/packages/@aws-cdk/aws-iam/test/group.test.ts index 6d0a4e83e05cc..7ea6580d51ea9 100644 --- a/packages/@aws-cdk/aws-iam/test/group.test.ts +++ b/packages/@aws-cdk/aws-iam/test/group.test.ts @@ -1,4 +1,4 @@ -import { Template } from '@aws-cdk/assertions'; +import { Annotations, Template } from '@aws-cdk/assertions'; import { App, CfnResource, Stack } from '@aws-cdk/core'; import { Group, ManagedPolicy, User } from '../lib'; @@ -103,3 +103,44 @@ test('cross-env group ARNs include path', () => { }, }); }); + +test('throw warning if attached managed policies exceed 10 in constructor', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new Group(stack, 'MyGroup', { + groupName: 'MyGroup', + managedPolicies: [ + ManagedPolicy.fromAwsManagedPolicyName('0'), + ManagedPolicy.fromAwsManagedPolicyName('1'), + ManagedPolicy.fromAwsManagedPolicyName('2'), + ManagedPolicy.fromAwsManagedPolicyName('3'), + ManagedPolicy.fromAwsManagedPolicyName('4'), + ManagedPolicy.fromAwsManagedPolicyName('5'), + ManagedPolicy.fromAwsManagedPolicyName('6'), + ManagedPolicy.fromAwsManagedPolicyName('7'), + ManagedPolicy.fromAwsManagedPolicyName('8'), + ManagedPolicy.fromAwsManagedPolicyName('9'), + ManagedPolicy.fromAwsManagedPolicyName('10'), + ], + }); + + Annotations.fromStack(stack).hasWarning('*', 'You added 11 to IAM Group MyGroup. The maximum number of managed policies attached to an IAM group is 10.'); +}); + +test('throw warning if attached managed policies exceed 10 when calling `addManagedPolicy`', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + const group = new Group(stack, 'MyGroup', { + groupName: 'MyGroup', + }); + + for (let i = 0; i <= 11; i++) { + group.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName(i.toString())); + } + + Annotations.fromStack(stack).hasWarning('/Default/MyGroup', 'You added 11 to IAM Group MyGroup. The maximum number of managed policies attached to an IAM group is 10.'); +}); diff --git a/packages/@aws-cdk/aws-iam/test/integ.saml-provider.js.snapshot/tree.json b/packages/@aws-cdk/aws-iam/test/integ.saml-provider.js.snapshot/tree.json index da6df90bfebae..dbd98dca5b2a3 100644 --- a/packages/@aws-cdk/aws-iam/test/integ.saml-provider.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-iam/test/integ.saml-provider.js.snapshot/tree.json @@ -117,7 +117,7 @@ "path": "saml-provider-test/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.249" + "version": "10.1.252" } }, "DeployAssert": { @@ -163,7 +163,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.249" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-iam/test/integ.saml-provider.ts b/packages/@aws-cdk/aws-iam/test/integ.saml-provider.ts index 2866e4d3e8e09..57f35b21d1afd 100644 --- a/packages/@aws-cdk/aws-iam/test/integ.saml-provider.ts +++ b/packages/@aws-cdk/aws-iam/test/integ.saml-provider.ts @@ -1,3 +1,4 @@ +/// !cdk-integ saml* import * as path from 'path'; import { App, Stack, StackProps } from '@aws-cdk/core'; import { IntegTest } from '@aws-cdk/integ-tests'; diff --git a/packages/@aws-cdk/aws-iotevents/package.json b/packages/@aws-cdk/aws-iotevents/package.json index 82ec19dfb76e6..7831b2838a1ad 100644 --- a/packages/@aws-cdk/aws-iotevents/package.json +++ b/packages/@aws-cdk/aws-iotevents/package.json @@ -85,6 +85,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/cdk.out b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/detector-model-test-stack.assets.json b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/detector-model-test-stack.assets.json index a83fe11ec9179..656035b275ddb 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/detector-model-test-stack.assets.json +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/detector-model-test-stack.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "142fd9106d7d51034f9c3594f2af5eaa1feff13065dca63084f39e0c91149152": { "source": { diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/integ.json b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/integ.json index fec20ecacc35b..2a7e55ea6eaaa 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ.detector-model": { "stacks": [ diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/manifest.json b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/manifest.json index d28706da19798..e5b38a85a52ed 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "detector-model-test-stack.assets": { "type": "cdk:asset-manifest", "properties": { @@ -71,6 +65,12 @@ ] }, "displayName": "detector-model-test-stack" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/tree.json b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/tree.json index 587fd03203339..d4e395020ed64 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "detector-model-test-stack": { "id": "detector-model-test-stack", "path": "detector-model-test-stack", @@ -58,6 +50,14 @@ "id": "DetectorModelRole", "path": "detector-model-test-stack/MyDetectorModel/DetectorModelRole", "children": { + "ImportDetectorModelRole": { + "id": "ImportDetectorModelRole", + "path": "detector-model-test-stack/MyDetectorModel/DetectorModelRole/ImportDetectorModelRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "detector-model-test-stack/MyDetectorModel/DetectorModelRole/Resource", @@ -227,17 +227,41 @@ "fqn": "@aws-cdk/aws-iotevents.DetectorModel", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "detector-model-test-stack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "detector-model-test-stack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts index 1c3996b226623..856e74e6af044 100644 --- a/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts +++ b/packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts @@ -1,4 +1,5 @@ import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as iotevents from '../lib'; class TestStack extends cdk.Stack { @@ -68,5 +69,6 @@ class TestStack extends cdk.Stack { } const app = new cdk.App(); -new TestStack(app, 'detector-model-test-stack'); -app.synth(); +new IntegTest(app, 'cdk-integ-detector-model-test-stack', { + testCases: [new TestStack(app, 'detector-model-test-stack')], +}); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index c0a233f9b1e00..d84acd65d1fde 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -81,7 +81,7 @@ "@aws-cdk/triggers": "0.0.0", "@types/jest": "^27.5.2", "delay": "5.0.0", - "esbuild": "^0.17.8" + "esbuild": "^0.17.10" }, "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 6fe5c6d2e7833..9c5efe90094cd 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -91,7 +91,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/cfnspec": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "@types/lodash": "^4.14.191", "@aws-cdk/aws-ssm": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.assets.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.assets.json index 2bf00b6e59333..029e733f879ae 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.assets.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { - "db659d970a5c19f47e5b73f555e343ee0dbc0d912df8c8b17b6fa0ebfab283b8": { + "99f646d44e5cdeefa552647d4c7ab32663f1ba5316065e52de38d8530187ab1d": { "source": { "path": "aws-cdk-lambda-1.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "db659d970a5c19f47e5b73f555e343ee0dbc0d912df8c8b17b6fa0ebfab283b8.json", + "objectKey": "99f646d44e5cdeefa552647d4c7ab32663f1ba5316065e52de38d8530187ab1d.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.template.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.template.json index 533cfb5d55526..1197d43cbbd41 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.template.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/aws-cdk-lambda-1.template.json @@ -456,6 +456,12 @@ "FileSystemId": { "Ref": "Efs9E8BF36B" }, + "AccessPointTags": [ + { + "Key": "Name", + "Value": "aws-cdk-lambda-1/Efs/AccessPoint" + } + ], "PosixUser": { "Gid": "1001", "Uid": "1001" diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/integ.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/integ.json index 1b9167c9341cb..4e4f69a9e5e34 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "integ.lambda.filesystem": { "stacks": [ diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/manifest.json index 8c79792676aa1..3fcc769449284 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-lambda-1.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/db659d970a5c19f47e5b73f555e343ee0dbc0d912df8c8b17b6fa0ebfab283b8.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/99f646d44e5cdeefa552647d4c7ab32663f1ba5316065e52de38d8530187ab1d.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -269,6 +263,12 @@ ] }, "displayName": "aws-cdk-lambda-1" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/tree.json b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/tree.json index f9eaeccd551b2..09d8a80dd8a6b 100644 --- a/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-lambda/test/integ.lambda.filesystem.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-lambda-1": { "id": "aws-cdk-lambda-1", "path": "aws-cdk-lambda-1", @@ -771,6 +763,12 @@ "fileSystemId": { "Ref": "Efs9E8BF36B" }, + "accessPointTags": [ + { + "key": "Name", + "value": "aws-cdk-lambda-1/Efs/AccessPoint" + } + ], "posixUser": { "uid": "1001", "gid": "1001" @@ -810,6 +808,14 @@ "id": "ServiceRole", "path": "aws-cdk-lambda-1/MyLambda/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-lambda-1/MyLambda/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-lambda-1/MyLambda/ServiceRole/Resource", @@ -1133,6 +1139,14 @@ "id": "ServiceRole", "path": "aws-cdk-lambda-1/MyLambda2/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-lambda-1/MyLambda2/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-lambda-1/MyLambda2/ServiceRole/Resource", @@ -1392,12 +1406,36 @@ "fqn": "@aws-cdk/aws-lambda.Function", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-lambda-1/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-lambda-1/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/PlaceIndexTestDefaultTestDeployAssert3F96C508.assets.json b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/PlaceIndexTestDefaultTestDeployAssert3F96C508.assets.json index 1c758b7b305ec..a555cd92a895d 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/PlaceIndexTestDefaultTestDeployAssert3F96C508.assets.json +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/PlaceIndexTestDefaultTestDeployAssert3F96C508.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk-integ-location-place-index.assets.json b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk-integ-location-place-index.assets.json index 92d001c5e2482..f16f86049d18c 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk-integ-location-place-index.assets.json +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk-integ-location-place-index.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "94bd94a7c3b98a6be66d32f390a66e2768617691c6d6f2bff2884647475cdaf4": { "source": { diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk.out b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/integ.json b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/integ.json index b8d0815ec42db..87157de9bfc96 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "PlaceIndexTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/manifest.json b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/manifest.json index 8b8b90d022243..d037d82f8afdb 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "cdk-integ-location-place-index.assets": { "type": "cdk:asset-manifest", diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/tree.json b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/tree.json index c498288355b3a..b79faad57bdb3 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.js.snapshot/tree.json @@ -68,7 +68,7 @@ "path": "PlaceIndexTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } }, "DeployAssert": { @@ -114,7 +114,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-location/test/integ.place-index.ts b/packages/@aws-cdk/aws-location/test/integ.place-index.ts index 738f5608e451c..1e6a50f403451 100644 --- a/packages/@aws-cdk/aws-location/test/integ.place-index.ts +++ b/packages/@aws-cdk/aws-location/test/integ.place-index.ts @@ -16,5 +16,3 @@ const app = new App(); new integ.IntegTest(app, 'PlaceIndexTest', { testCases: [new TestStack(app, 'cdk-integ-location-place-index')], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-logs/package.json b/packages/@aws-cdk/aws-logs/package.json index 41dff1f9d17dd..56ae9b9b1293d 100644 --- a/packages/@aws-cdk/aws-logs/package.json +++ b/packages/@aws-cdk/aws-logs/package.json @@ -86,10 +86,10 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "@types/sinon": "^9.0.11", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1", "nock": "^13.3.0", diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts index 9c43f8350fb6e..6c61051c5938f 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts @@ -412,6 +412,10 @@ export class AuroraMysqlEngineVersion { public static readonly VER_2_10_2 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.2'); /** Version "5.7.mysql_aurora.2.10.3". */ public static readonly VER_2_10_3 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.3'); + /** Version "5.7.mysql_aurora.2.11.0". */ + public static readonly VER_2_11_0 = AuroraMysqlEngineVersion.builtIn_5_7('2.11.0'); + /** Version "5.7.mysql_aurora.2.11.1". */ + public static readonly VER_2_11_1 = AuroraMysqlEngineVersion.builtIn_5_7('2.11.1'); /** Version "8.0.mysql_aurora.3.01.0". */ public static readonly VER_3_01_0 = AuroraMysqlEngineVersion.builtIn_8_0('3.01.0'); /** Version "8.0.mysql_aurora.3.01.1". */ @@ -420,6 +424,8 @@ export class AuroraMysqlEngineVersion { public static readonly VER_3_02_0 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.0'); /** Version "8.0.mysql_aurora.3.02.1". */ public static readonly VER_3_02_1 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.1'); + /** Version "8.0.mysql_aurora.3.02.2". */ + public static readonly VER_3_02_2 = AuroraMysqlEngineVersion.builtIn_8_0('3.02.2'); /** * Create a new AuroraMysqlEngineVersion with an arbitrary version. diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index 4d85631b02ba1..11f2e7cf2d1c3 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -568,6 +568,8 @@ export class MysqlEngineVersion { public static readonly VER_5_7_39 = MysqlEngineVersion.of('5.7.39', '5.7'); /** Version "5.7.40". */ public static readonly VER_5_7_40 = MysqlEngineVersion.of('5.7.40', '5.7'); + /** Version "5.7.41". */ + public static readonly VER_5_7_41 = MysqlEngineVersion.of('5.7.41', '5.7'); /** Version "8.0" (only a major version, without a specific minor version). */ public static readonly VER_8_0 = MysqlEngineVersion.of('8.0', '8.0'); @@ -601,6 +603,8 @@ export class MysqlEngineVersion { public static readonly VER_8_0_30 = MysqlEngineVersion.of('8.0.30', '8.0'); /** Version "8.0.31". */ public static readonly VER_8_0_31 = MysqlEngineVersion.of('8.0.31', '8.0'); + /** Version "8.0.32". */ + public static readonly VER_8_0_32 = MysqlEngineVersion.of('8.0.32', '8.0'); /** * Create a new MysqlEngineVersion with an arbitrary version. @@ -1328,6 +1332,9 @@ export class OracleEngineVersion { public static readonly VER_19_0_0_0_2022_07_R1 = OracleEngineVersion.of('19.0.0.0.ru-2022-07.rur-2022-07.r1', '19'); /** Version "19.0.0.0.ru-2022-10.rur-2022-10.r1". */ public static readonly VER_19_0_0_0_2022_10_R1 = OracleEngineVersion.of('19.0.0.0.ru-2022-10.rur-2022-10.r1', '19'); + /** Version "19.0.0.0.ru-2023-01.rur-2023-01.r1". */ + public static readonly VER_19_0_0_0_2023_01_R1 = OracleEngineVersion.of('19.0.0.0.ru-2023-01.rur-2023-01.r1', '19'); + /** Version "21" (only a major version, without a specific minor version). */ public static readonly VER_21 = OracleEngineVersion.of('21', '21'); @@ -1339,6 +1346,8 @@ export class OracleEngineVersion { public static readonly VER_21_0_0_0_2022_07_R1 = OracleEngineVersion.of('21.0.0.0.ru-2022-07.rur-2022-07.r1', '21'); /** Version "21.0.0.0.ru-2022-10.rur-2022-10.r1". */ public static readonly VER_21_0_0_0_2022_10_R1 = OracleEngineVersion.of('21.0.0.0.ru-2022-10.rur-2022-10.r1', '21'); + /** Version "21.0.0.0.ru-2023-01.rur-2023-01.r1". */ + public static readonly VER_21_0_0_0_2023_01_R1 = OracleEngineVersion.of('21.0.0.0.ru-2023-01.rur-2023-01.r1', '21'); /** * Creates a new OracleEngineVersion with an arbitrary version. diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json index ae1f3168553a8..6256aa3105eec 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.assets.json @@ -1,7 +1,7 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { - "dfc2f8e8aa2f2f42357312f7f92524a12cb383c762b91eaecbbefb8ad8400f82": { + "f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490": { "source": { "path": "aws-cdk-rds-cluster-rotation.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "dfc2f8e8aa2f2f42357312f7f92524a12cb383c762b91eaecbbefb8ad8400f82.json", + "objectKey": "f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json index bd800aaa20877..0252e7533406a 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/aws-cdk-rds-cluster-rotation.template.json @@ -606,7 +606,7 @@ } } }, - "DatabaseSecretAttachmentPolicy5ACFE6CA": { + "DatabaseSecretPolicyEE73D3F8": { "Type": "AWS::SecretsManager::ResourcePolicy", "Properties": { "ResourcePolicy": { @@ -638,18 +638,18 @@ "Version": "2012-10-17" }, "SecretId": { - "Ref": "DatabaseSecretAttachmentE5D1B020" + "Ref": "DatabaseSecret3B817195" } } }, "DatabaseB269D8BB": { "Type": "AWS::RDS::DBCluster", "Properties": { - "Engine": "aurora", "CopyTagsToSnapshot": true, "DBSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "Engine": "aurora", "MasterUsername": { "Fn::Join": [ "", @@ -924,7 +924,7 @@ } } }, - "CustomRotationOptionsSecretAttachmentPolicyAB818C64": { + "CustomRotationOptionsSecretPolicyA73E17A8": { "Type": "AWS::SecretsManager::ResourcePolicy", "Properties": { "ResourcePolicy": { @@ -956,18 +956,18 @@ "Version": "2012-10-17" }, "SecretId": { - "Ref": "CustomRotationOptionsSecretAttachment697A23BF" + "Ref": "CustomRotationOptionsSecret7DCFFFDB" } } }, "CustomRotationOptions7CA9E132": { "Type": "AWS::RDS::DBCluster", "Properties": { - "Engine": "aurora", "CopyTagsToSnapshot": true, "DBSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, + "Engine": "aurora", "MasterUsername": { "Fn::Join": [ "", diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json index 3cee3075c64cc..5bbe8121413b0 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "integ.cluster-rotation.lit": { "stacks": [ diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json index 21ee20339ed5f..0da5ccc5e746a 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-rds-cluster-rotation.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/dfc2f8e8aa2f2f42357312f7f92524a12cb383c762b91eaecbbefb8ad8400f82.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f1be03db0810455e897d5600a00d7d089273d1f89b9a319be25928bf241a9490.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -225,10 +225,10 @@ "data": "DatabaseSecretAttachmentRotationScheduleA4E9F034" } ], - "/aws-cdk-rds-cluster-rotation/Database/Secret/Attachment/Policy/Resource": [ + "/aws-cdk-rds-cluster-rotation/Database/Secret/Policy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseSecretAttachmentPolicy5ACFE6CA" + "data": "DatabaseSecretPolicyEE73D3F8" } ], "/aws-cdk-rds-cluster-rotation/Database/Resource": [ @@ -264,10 +264,7 @@ "/aws-cdk-rds-cluster-rotation/Database/RotationSingleUser/Resource": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseRotationSingleUser65F55654", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "DatabaseRotationSingleUser65F55654" } ], "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Subnets/Default": [ @@ -306,10 +303,10 @@ "data": "CustomRotationOptionsSecretAttachmentRotationScheduleD5AEB622" } ], - "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Attachment/Policy/Resource": [ + "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Policy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "CustomRotationOptionsSecretAttachmentPolicyAB818C64" + "data": "CustomRotationOptionsSecretPolicyA73E17A8" } ], "/aws-cdk-rds-cluster-rotation/CustomRotationOptions/Resource": [ @@ -354,10 +351,19 @@ "data": "CheckBootstrapVersion" } ], - "DatabaseSecurityGroupfromawscdkrdsclusterrotationSecurityGroupB986D266IndirectPortE461A61D": [ + "DatabaseSecretAttachmentPolicy5ACFE6CA": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseSecretAttachmentPolicy5ACFE6CA", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "CustomRotationOptionsSecretAttachmentPolicyAB818C64": [ { "type": "aws:cdk:logicalId", - "data": "DatabaseSecurityGroupfromawscdkrdsclusterrotationSecurityGroupB986D266IndirectPortE461A61D", + "data": "CustomRotationOptionsSecretAttachmentPolicyAB818C64", "trace": [ "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" ] diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json index 756823a7c2091..5eefe4ba0e14b 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-rotation.lit.js.snapshot/tree.json @@ -1004,64 +1004,64 @@ "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", "version": "0.0.0" } - }, - "Policy": { - "id": "Policy", - "path": "aws-cdk-rds-cluster-rotation/Database/Secret/Attachment/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-cluster-rotation/Database/Secret/Attachment/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", - "aws:cdk:cloudformation:props": { - "resourcePolicy": { - "Statement": [ - { - "Action": "secretsmanager:DeleteSecret", - "Effect": "Deny", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-rds-cluster-rotation/Database/Secret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-cluster-rotation/Database/Secret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] } - ], - "Version": "2012-10-17" - }, - "secretId": { - "Ref": "DatabaseSecretAttachmentE5D1B020" + }, + "Resource": "*" } - } + ], + "Version": "2012-10-17" }, - "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "secretId": { + "Ref": "DatabaseSecret3B817195" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", "version": "0.0.0" } } @@ -1077,11 +1077,11 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { - "engine": "aurora", "copyTagsToSnapshot": true, "dbSubnetGroupName": { "Ref": "DatabaseSubnets56F17B9A" }, + "engine": "aurora", "masterUsername": { "Fn::Join": [ "", @@ -1502,64 +1502,64 @@ "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", "version": "0.0.0" } - }, - "Policy": { - "id": "Policy", - "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Attachment/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Attachment/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", - "aws:cdk:cloudformation:props": { - "resourcePolicy": { - "Statement": [ - { - "Action": "secretsmanager:DeleteSecret", - "Effect": "Deny", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-cluster-rotation/CustomRotationOptions/Secret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] } - ], - "Version": "2012-10-17" - }, - "secretId": { - "Ref": "CustomRotationOptionsSecretAttachment697A23BF" + }, + "Resource": "*" } - } + ], + "Version": "2012-10-17" }, - "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "secretId": { + "Ref": "CustomRotationOptionsSecret7DCFFFDB" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", "version": "0.0.0" } } @@ -1575,11 +1575,11 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { - "engine": "aurora", "copyTagsToSnapshot": true, "dbSubnetGroupName": { "Ref": "CustomRotationOptionsSubnets52AEBCED" }, + "engine": "aurora", "masterUsername": { "Fn::Join": [ "", @@ -1796,7 +1796,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.161" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js similarity index 100% rename from packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/cfn-response.js rename to packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/cfn-response.js diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js similarity index 100% rename from packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/consts.js rename to packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/consts.js diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js similarity index 100% rename from packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/framework.js rename to packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/framework.js diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js new file mode 100644 index 0000000000000..cc0667d42f0e8 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/outbound.js @@ -0,0 +1,69 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; +/* istanbul ignore file */ +const https = require("https"); +// eslint-disable-next-line import/no-extraneous-dependencies +const AWS = require("aws-sdk"); +const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes +// In order to honor the overall maximum timeout set for the target process, +// the default 2 minutes from AWS SDK has to be overriden: +// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property +const awsSdkConfig = { + httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, +}; +async function defaultHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, resolve); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +let sfn; +let lambda; +async function defaultStartExecution(req) { + if (!sfn) { + sfn = new AWS.StepFunctions(awsSdkConfig); + } + return sfn.startExecution(req).promise(); +} +async function defaultInvokeFunction(req) { + if (!lambda) { + lambda = new AWS.Lambda(awsSdkConfig); + } + try { + /** + * Try an initial invoke. + * + * When you try to invoke a function that is inactive, the invocation fails and Lambda sets + * the function to pending state until the function resources are recreated. + * If Lambda fails to recreate the resources, the function is set to the inactive state. + * + * We're using invoke first because `waitFor` doesn't trigger an inactive function to do anything, + * it just runs `getFunction` and checks the state. + */ + return await lambda.invoke(req).promise(); + } + catch (error) { + /** + * The status of the Lambda function is checked every second for up to 300 seconds. + * Exits the loop on 'Active' state and throws an error on 'Inactive' or 'Failed'. + * + * And now we wait. + */ + await lambda.waitFor('functionActiveV2', { + FunctionName: req.FunctionName, + }).promise(); + return await lambda.invoke(req).promise(); + } +} +exports.startExecution = defaultStartExecution; +exports.invokeFunction = defaultInvokeFunction; +exports.httpRequest = defaultHttpRequest; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELElBQUk7UUFDRjs7Ozs7Ozs7O1dBU0c7UUFDSCxPQUFPLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztLQUMzQztJQUFDLE9BQU8sS0FBSyxFQUFFO1FBRWQ7Ozs7O1dBS0c7UUFDSCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLEVBQUU7WUFDdkMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZO1NBQy9CLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO0tBQzNDO0FBQ0gsQ0FBQztBQUVVLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsY0FBYyxHQUFHLHFCQUFxQixDQUFDO0FBQ3ZDLFFBQUEsV0FBVyxHQUFHLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogaXN0YW5idWwgaWdub3JlIGZpbGUgKi9cbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5cbmNvbnN0IEZSQU1FV09SS19IQU5ETEVSX1RJTUVPVVQgPSA5MDAwMDA7IC8vIDE1IG1pbnV0ZXNcblxuLy8gSW4gb3JkZXIgdG8gaG9ub3IgdGhlIG92ZXJhbGwgbWF4aW11bSB0aW1lb3V0IHNldCBmb3IgdGhlIHRhcmdldCBwcm9jZXNzLFxuLy8gdGhlIGRlZmF1bHQgMiBtaW51dGVzIGZyb20gQVdTIFNESyBoYXMgdG8gYmUgb3ZlcnJpZGVuOlxuLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0phdmFTY3JpcHRTREsvbGF0ZXN0L0FXUy9Db25maWcuaHRtbCNodHRwT3B0aW9ucy1wcm9wZXJ0eVxuY29uc3QgYXdzU2RrQ29uZmlnOiBDb25maWd1cmF0aW9uT3B0aW9ucyA9IHtcbiAgaHR0cE9wdGlvbnM6IHsgdGltZW91dDogRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCB9LFxufTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEh0dHBSZXF1ZXN0KG9wdGlvbnM6IGh0dHBzLlJlcXVlc3RPcHRpb25zLCByZXNwb25zZUJvZHk6IHN0cmluZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChvcHRpb25zLCByZXNvbHZlKTtcbiAgICAgIHJlcXVlc3Qub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICAgIHJlcXVlc3Qud3JpdGUocmVzcG9uc2VCb2R5KTtcbiAgICAgIHJlcXVlc3QuZW5kKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmVqZWN0KGUpO1xuICAgIH1cbiAgfSk7XG59XG5cbmxldCBzZm46IEFXUy5TdGVwRnVuY3Rpb25zO1xubGV0IGxhbWJkYTogQVdTLkxhbWJkYTtcblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFN0YXJ0RXhlY3V0aW9uKHJlcTogQVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25JbnB1dCk6IFByb21pc2U8QVdTLlN0ZXBGdW5jdGlvbnMuU3RhcnRFeGVjdXRpb25PdXRwdXQ+IHtcbiAgaWYgKCFzZm4pIHtcbiAgICBzZm4gPSBuZXcgQVdTLlN0ZXBGdW5jdGlvbnMoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBzZm4uc3RhcnRFeGVjdXRpb24ocmVxKS5wcm9taXNlKCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRlZmF1bHRJbnZva2VGdW5jdGlvbihyZXE6IEFXUy5MYW1iZGEuSW52b2NhdGlvblJlcXVlc3QpOiBQcm9taXNlPEFXUy5MYW1iZGEuSW52b2NhdGlvblJlc3BvbnNlPiB7XG4gIGlmICghbGFtYmRhKSB7XG4gICAgbGFtYmRhID0gbmV3IEFXUy5MYW1iZGEoYXdzU2RrQ29uZmlnKTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLyoqXG4gICAgICogVHJ5IGFuIGluaXRpYWwgaW52b2tlLlxuICAgICAqXG4gICAgICogV2hlbiB5b3UgdHJ5IHRvIGludm9rZSBhIGZ1bmN0aW9uIHRoYXQgaXMgaW5hY3RpdmUsIHRoZSBpbnZvY2F0aW9uIGZhaWxzIGFuZCBMYW1iZGEgc2V0c1xuICAgICAqIHRoZSBmdW5jdGlvbiB0byBwZW5kaW5nIHN0YXRlIHVudGlsIHRoZSBmdW5jdGlvbiByZXNvdXJjZXMgYXJlIHJlY3JlYXRlZC5cbiAgICAgKiBJZiBMYW1iZGEgZmFpbHMgdG8gcmVjcmVhdGUgdGhlIHJlc291cmNlcywgdGhlIGZ1bmN0aW9uIGlzIHNldCB0byB0aGUgaW5hY3RpdmUgc3RhdGUuXG4gICAgICpcbiAgICAgKiBXZSdyZSB1c2luZyBpbnZva2UgZmlyc3QgYmVjYXVzZSBgd2FpdEZvcmAgZG9lc24ndCB0cmlnZ2VyIGFuIGluYWN0aXZlIGZ1bmN0aW9uIHRvIGRvIGFueXRoaW5nLFxuICAgICAqIGl0IGp1c3QgcnVucyBgZ2V0RnVuY3Rpb25gIGFuZCBjaGVja3MgdGhlIHN0YXRlLlxuICAgICAqL1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9IGNhdGNoIChlcnJvcikge1xuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YXR1cyBvZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIGlzIGNoZWNrZWQgZXZlcnkgc2Vjb25kIGZvciB1cCB0byAzMDAgc2Vjb25kcy5cbiAgICAgKiBFeGl0cyB0aGUgbG9vcCBvbiAnQWN0aXZlJyBzdGF0ZSBhbmQgdGhyb3dzIGFuIGVycm9yIG9uICdJbmFjdGl2ZScgb3IgJ0ZhaWxlZCcuXG4gICAgICpcbiAgICAgKiBBbmQgbm93IHdlIHdhaXQuXG4gICAgICovXG4gICAgYXdhaXQgbGFtYmRhLndhaXRGb3IoJ2Z1bmN0aW9uQWN0aXZlVjInLCB7XG4gICAgICBGdW5jdGlvbk5hbWU6IHJlcS5GdW5jdGlvbk5hbWUsXG4gICAgfSkucHJvbWlzZSgpO1xuICAgIHJldHVybiBhd2FpdCBsYW1iZGEuaW52b2tlKHJlcSkucHJvbWlzZSgpO1xuICB9XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js similarity index 100% rename from packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/util.js rename to packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585/util.js diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.assets.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.assets.json index 52f14f55deb74..91d24983fc3c9 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.assets.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "2e7ee01d9005281c0784e709cad69500591734343d1cb95da2fb4a3f5076aadd": { "source": { @@ -14,20 +14,20 @@ } } }, - "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037": { + "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585": { "source": { - "path": "asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037", + "path": "asset.a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip", + "objectKey": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "58fc394d5f5f45f41e0b793cb553bcba2bb2899eec75a6b2e00e1df08ad19eff": { + "f52756563b89062acac165275c62a93cfda25f7fa3aed987a65809db27bc37a5": { "source": { "path": "cdk-integ-cluster-snapshot.template.json", "packaging": "file" @@ -35,7 +35,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "58fc394d5f5f45f41e0b793cb553bcba2bb2899eec75a6b2e00e1df08ad19eff.json", + "objectKey": "f52756563b89062acac165275c62a93cfda25f7fa3aed987a65809db27bc37a5.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.template.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.template.json index ecff73b539c94..5a9b5e79c4b51 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.template.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk-integ-cluster-snapshot.template.json @@ -425,12 +425,12 @@ "ClusterEB0386A7": { "Type": "AWS::RDS::DBCluster", "Properties": { - "Engine": "aurora-mysql", "CopyTagsToSnapshot": true, "DBClusterParameterGroupName": "default.aurora-mysql5.7", "DBSubnetGroupName": { "Ref": "ClusterSubnetsDCFA5CB7" }, + "Engine": "aurora-mysql", "EngineVersion": "5.7.mysql_aurora.2.10.2", "MasterUsername": { "Fn::Join": [ @@ -858,7 +858,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -995,7 +995,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -1129,7 +1129,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "S3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "Role": { "Fn::GetAtt": [ @@ -1446,7 +1446,7 @@ } } }, - "FromSnapshotSnapshotSecretAttachmentPolicy3136FEC0": { + "FromSnapshotSnapshotSecretPolicyA5C332BE": { "Type": "AWS::SecretsManager::ResourcePolicy", "Properties": { "ResourcePolicy": { @@ -1478,19 +1478,19 @@ "Version": "2012-10-17" }, "SecretId": { - "Ref": "FromSnapshotSnapshotSecretAttachmentA3F619B8" + "Ref": "cdkintegclustersnapshotFromSnapshotSnapshotSecretD93327943fdaad7efa858a3daf9490cf0a702aeb" } } }, "FromSnapshotEE0682C5": { "Type": "AWS::RDS::DBCluster", "Properties": { - "Engine": "aurora-mysql", "CopyTagsToSnapshot": true, "DBClusterParameterGroupName": "default.aurora-mysql5.7", "DBSubnetGroupName": { "Ref": "FromSnapshotSubnets9ED4B8EE" }, + "Engine": "aurora-mysql", "EngineVersion": "5.7.mysql_aurora.2.10.2", "MasterUserPassword": { "Fn::Join": [ diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk.out b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/integ.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/integ.json index 329077c22006c..daa81ef94fabf 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { "integ.cluster-snapshot": { "stacks": [ diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/manifest.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/manifest.json index 323e4184407ac..f386e19c0f970 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { "cdk-integ-cluster-snapshot.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/58fc394d5f5f45f41e0b793cb553bcba2bb2899eec75a6b2e00e1df08ad19eff.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f52756563b89062acac165275c62a93cfda25f7fa3aed987a65809db27bc37a5.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -363,10 +363,10 @@ "data": "FromSnapshotSnapshotSecretAttachmentRotationSchedule102BDEB3" } ], - "/cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Attachment/Policy/Resource": [ + "/cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Policy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "FromSnapshotSnapshotSecretAttachmentPolicy3136FEC0" + "data": "FromSnapshotSnapshotSecretPolicyA5C332BE" } ], "/cdk-integ-cluster-snapshot/FromSnapshot/Resource": [ @@ -416,6 +416,15 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "FromSnapshotSnapshotSecretAttachmentPolicy3136FEC0": [ + { + "type": "aws:cdk:logicalId", + "data": "FromSnapshotSnapshotSecretAttachmentPolicy3136FEC0", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "cdk-integ-cluster-snapshot" diff --git a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/tree.json b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/tree.json index fa892eca6a00d..780a8f2d8ebc6 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-rds/test/integ.cluster-snapshot.js.snapshot/tree.json @@ -757,12 +757,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { - "engine": "aurora-mysql", "copyTagsToSnapshot": true, "dbClusterParameterGroupName": "default.aurora-mysql5.7", "dbSubnetGroupName": { "Ref": "ClusterSubnetsDCFA5CB7" }, + "engine": "aurora-mysql", "engineVersion": "5.7.mysql_aurora.2.10.2", "masterUsername": { "Fn::Join": [ @@ -863,6 +863,14 @@ "id": "ServiceRole", "path": "cdk-integ-cluster-snapshot/Snapshoter/OnEventHandler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/OnEventHandler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/OnEventHandler/ServiceRole/Resource", @@ -1061,6 +1069,14 @@ "id": "ServiceRole", "path": "cdk-integ-cluster-snapshot/Snapshoter/IsCompleteHandler/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/IsCompleteHandler/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/IsCompleteHandler/ServiceRole/Resource", @@ -1234,6 +1250,14 @@ "id": "ServiceRole", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onEvent/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onEvent/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onEvent/ServiceRole/Resource", @@ -1402,7 +1426,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -1454,6 +1478,14 @@ "id": "ServiceRole", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-isComplete/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-isComplete/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-isComplete/ServiceRole/Resource", @@ -1615,7 +1647,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -1664,6 +1696,14 @@ "id": "ServiceRole", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onTimeout/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onTimeout/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/framework-onTimeout/ServiceRole/Resource", @@ -1825,7 +1865,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037.zip" + "s3Key": "a8a62b989c7866e3ad5b24f3eb6228f8ca91ebff5f5c76f1da466f6c805c0585.zip" }, "role": { "Fn::GetAtt": [ @@ -1874,6 +1914,14 @@ "id": "Role", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/waiter-state-machine/Role", "children": { + "ImportRole": { + "id": "ImportRole", + "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/waiter-state-machine/Role/ImportRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "cdk-integ-cluster-snapshot/Snapshoter/SnapshotProvider/waiter-state-machine/Role/Resource", @@ -1996,7 +2044,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } } }, @@ -2026,7 +2074,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } }, "FromSnapshot": { @@ -2308,64 +2356,64 @@ "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", "version": "0.0.0" } - }, - "Policy": { - "id": "Policy", - "path": "cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Attachment/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Attachment/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", - "aws:cdk:cloudformation:props": { - "resourcePolicy": { - "Statement": [ - { - "Action": "secretsmanager:DeleteSecret", - "Effect": "Deny", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "cdk-integ-cluster-snapshot/FromSnapshot/SnapshotSecret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] } - ], - "Version": "2012-10-17" - }, - "secretId": { - "Ref": "FromSnapshotSnapshotSecretAttachmentA3F619B8" + }, + "Resource": "*" } - } + ], + "Version": "2012-10-17" }, - "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "secretId": { + "Ref": "cdkintegclustersnapshotFromSnapshotSnapshotSecretD93327943fdaad7efa858a3daf9490cf0a702aeb" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", "version": "0.0.0" } } @@ -2381,12 +2429,12 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { - "engine": "aurora-mysql", "copyTagsToSnapshot": true, "dbClusterParameterGroupName": "default.aurora-mysql5.7", "dbSubnetGroupName": { "Ref": "FromSnapshotSubnets9ED4B8EE" }, + "engine": "aurora-mysql", "engineVersion": "5.7.mysql_aurora.2.10.2", "masterUserPassword": { "Fn::Join": [ @@ -2628,7 +2676,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.140" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.assets.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.assets.json index 5867eb7ea2b91..06206b4bc735d 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.assets.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "d01c24641c7d8cb6488393ffceaefff282370a9a522bf9d77b21da73fa257347": { "source": { @@ -14,7 +14,7 @@ } } }, - "ca59a5a9368640ecbf25d69e1e3312350b2d7b735c3b73b031c02657142ca94b": { + "e7bc0b577d93d8f59c7fe5e6f67a018347fe8fe4ea16a012eba5a7504564f2e0": { "source": { "path": "aws-cdk-rds-instance.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "ca59a5a9368640ecbf25d69e1e3312350b2d7b735c3b73b031c02657142ca94b.json", + "objectKey": "e7bc0b577d93d8f59c7fe5e6f67a018347fe8fe4ea16a012eba5a7504564f2e0.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.template.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.template.json index 4f724da4a1845..1e7427c56b992 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.template.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/aws-cdk-rds-instance.template.json @@ -623,7 +623,7 @@ } } }, - "InstanceSecretAttachmentPolicy60A8B8DE": { + "InstanceSecretPolicy87F03D0F": { "Type": "AWS::SecretsManager::ResourcePolicy", "Properties": { "ResourcePolicy": { @@ -655,7 +655,7 @@ "Version": "2012-10-17" }, "SecretId": { - "Ref": "InstanceSecretAttachment83BEE581" + "Ref": "InstanceSecret478E0A47" } } }, diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/cdk.out b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/integ.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/integ.json index f00922c1b07f1..c82bfe665cd8e 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { "integ.instance.lit": { "stacks": [ diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/manifest.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/manifest.json index c78f81ebe89f1..95cadf434598f 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-rds-instance.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/ca59a5a9368640ecbf25d69e1e3312350b2d7b735c3b73b031c02657142ca94b.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e7bc0b577d93d8f59c7fe5e6f67a018347fe8fe4ea16a012eba5a7504564f2e0.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -243,10 +237,10 @@ "data": "InstanceSecretAttachmentRotationScheduleCC555119" } ], - "/aws-cdk-rds-instance/Instance/Secret/Attachment/Policy/Resource": [ + "/aws-cdk-rds-instance/Instance/Secret/Policy/Resource": [ { "type": "aws:cdk:logicalId", - "data": "InstanceSecretAttachmentPolicy60A8B8DE" + "data": "InstanceSecretPolicy87F03D0F" } ], "/aws-cdk-rds-instance/Instance/Resource": [ @@ -356,9 +350,24 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } + ], + "InstanceSecretAttachmentPolicy60A8B8DE": [ + { + "type": "aws:cdk:logicalId", + "data": "InstanceSecretAttachmentPolicy60A8B8DE", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } ] }, "displayName": "aws-cdk-rds-instance" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/tree.json b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/tree.json index 59040e2e6e3a0..504c4594cbf5b 100644 --- a/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-rds/test/integ.instance.lit.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-rds-instance": { "id": "aws-cdk-rds-instance", "path": "aws-cdk-rds-instance", @@ -91,8 +83,8 @@ "id": "Acl", "path": "aws-cdk-rds-instance/VPC/PublicSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -258,8 +250,8 @@ "id": "Acl", "path": "aws-cdk-rds-instance/VPC/PublicSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -425,8 +417,8 @@ "id": "Acl", "path": "aws-cdk-rds-instance/VPC/PrivateSubnet1/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -544,8 +536,8 @@ "id": "Acl", "path": "aws-cdk-rds-instance/VPC/PrivateSubnet2/Acl", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" } }, "RouteTable": { @@ -920,6 +912,14 @@ "id": "MonitoringRole", "path": "aws-cdk-rds-instance/Instance/MonitoringRole", "children": { + "ImportMonitoringRole": { + "id": "ImportMonitoringRole", + "path": "aws-cdk-rds-instance/Instance/MonitoringRole/ImportMonitoringRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-rds-instance/Instance/MonitoringRole/Resource", @@ -1057,64 +1057,64 @@ "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", "version": "0.0.0" } - }, - "Policy": { - "id": "Policy", - "path": "aws-cdk-rds-instance/Instance/Secret/Attachment/Policy", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-rds-instance/Instance/Secret/Attachment/Policy/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", - "aws:cdk:cloudformation:props": { - "resourcePolicy": { - "Statement": [ - { - "Action": "secretsmanager:DeleteSecret", - "Effect": "Deny", - "Principal": { - "AWS": { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":iam::", - { - "Ref": "AWS::AccountId" - }, - ":root" - ] - ] - } - }, - "Resource": "*" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-rds-instance/Instance/Secret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-instance/Instance/Secret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] } - ], - "Version": "2012-10-17" - }, - "secretId": { - "Ref": "InstanceSecretAttachment83BEE581" + }, + "Resource": "*" } - } + ], + "Version": "2012-10-17" }, - "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", - "version": "0.0.0" + "secretId": { + "Ref": "InstanceSecret478E0A47" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", "version": "0.0.0" } } }, "constructInfo": { - "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", "version": "0.0.0" } } @@ -1214,8 +1214,8 @@ "id": "Resource", "path": "aws-cdk-rds-instance/Instance/LogRetentiontrace/Resource", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, @@ -1232,8 +1232,8 @@ "id": "Resource", "path": "aws-cdk-rds-instance/Instance/LogRetentionaudit/Resource", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, @@ -1250,8 +1250,8 @@ "id": "Resource", "path": "aws-cdk-rds-instance/Instance/LogRetentionalert/Resource", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, @@ -1268,8 +1268,8 @@ "id": "Resource", "path": "aws-cdk-rds-instance/Instance/LogRetentionlistener/Resource", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, @@ -1320,8 +1320,8 @@ "id": "SARMapping", "path": "aws-cdk-rds-instance/Instance/RotationSingleUser/SARMapping", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnMapping", + "version": "0.0.0" } }, "Resource": { @@ -1525,8 +1525,8 @@ "id": "Stage", "path": "aws-cdk-rds-instance/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Code/Stage", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "AssetBucket": { @@ -1547,6 +1547,14 @@ "id": "ServiceRole", "path": "aws-cdk-rds-instance/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-rds-instance/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-rds-instance/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource", @@ -1638,14 +1646,14 @@ "id": "Resource", "path": "aws-cdk-rds-instance/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/Resource", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } }, "HighCPU": { @@ -1694,6 +1702,14 @@ "id": "ServiceRole", "path": "aws-cdk-rds-instance/Function/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-rds-instance/Function/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-rds-instance/Function/ServiceRole/Resource", @@ -1768,17 +1784,41 @@ "fqn": "@aws-cdk/aws-lambda.Function", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-rds-instance/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-rds-instance/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.assets.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.assets.json new file mode 100644 index 0000000000000..c67db596bcf31 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "3b78e7a70e98ec500faa058ecc14892c94df0ab8d0359ba99718203b67d4a2e6": { + "source": { + "path": "aws-cdk-rds-integ-secret-rotation.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "3b78e7a70e98ec500faa058ecc14892c94df0ab8d0359ba99718203b67d4a2e6.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/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.template.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.template.json new file mode 100644 index 0000000000000..84e9db49cabdc --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/aws-cdk-rds-integ-secret-rotation.template.json @@ -0,0 +1,234 @@ +{ + "Transform": "AWS::SecretsManager-2020-07-23", + "Resources": { + "DbSecurity381C2C15": { + "Type": "AWS::KMS::Key", + "Properties": { + "KeyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "testsecretF8BBC644": { + "Type": "AWS::SecretsManager::Secret", + "Properties": { + "Description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "GenerateSecretString": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "GenerateStringKey": "password", + "PasswordLength": 30, + "SecretStringTemplate": "{\"username\":\"admin\"}" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "testsecretAttachment19AD251F": { + "Type": "AWS::SecretsManager::SecretTargetAttachment", + "Properties": { + "SecretId": { + "Ref": "testsecretF8BBC644" + }, + "TargetId": { + "Ref": "DatabaseB269D8BB" + }, + "TargetType": "AWS::RDS::DBCluster" + } + }, + "testsecrettestscheduleEA0B5085": { + "Type": "AWS::SecretsManager::RotationSchedule", + "Properties": { + "SecretId": { + "Ref": "testsecretF8BBC644" + }, + "HostedRotationLambda": { + "ExcludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\", + "RotationType": "MySQLSingleUser" + }, + "RotationRules": { + "AutomaticallyAfterDays": 30 + } + } + }, + "testsecretPolicyA5D2F46F": { + "Type": "AWS::SecretsManager::ResourcePolicy", + "Properties": { + "ResourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + }, + "Service": "ecs-tasks.amazonaws.com" + }, + "Resource": { + "Ref": "testsecretAttachment19AD251F" + } + } + ], + "Version": "2012-10-17" + }, + "SecretId": { + "Ref": "testsecretF8BBC644" + } + } + }, + "DatabaseB269D8BB": { + "Type": "AWS::RDS::DBCluster", + "Properties": { + "CopyTagsToSnapshot": true, + "DBClusterParameterGroupName": "default.aurora-mysql5.7", + "EnableHttpEndpoint": true, + "Engine": "aurora-mysql", + "EngineMode": "serverless", + "KmsKeyId": { + "Fn::GetAtt": [ + "DbSecurity381C2C15", + "Arn" + ] + }, + "MasterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "testsecretF8BBC644" + }, + ":SecretString:username::}}" + ] + ] + }, + "MasterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "testsecretF8BBC644" + }, + ":SecretString:password::}}" + ] + ] + }, + "StorageEncrypted": true, + "VpcSecurityGroupIds": [] + }, + "UpdateReplacePolicy": "Snapshot", + "DeletionPolicy": "Snapshot" + } + }, + "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/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdk.out b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdk.out new file mode 100644 index 0000000000000..b72fef144f05c --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets.json new file mode 100644 index 0000000000000..b8d0a12323139 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.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/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.template.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.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/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/integ.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/integ.json new file mode 100644 index 0000000000000..796211c1a7c05 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "30.1.0", + "testCases": { + "cdk-rds-integ-secret-rotation/DefaultTest": { + "stacks": [ + "aws-cdk-rds-integ-secret-rotation" + ], + "assertionStack": "cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert", + "assertionStackName": "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/manifest.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/manifest.json new file mode 100644 index 0000000000000..db97d586370c2 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/manifest.json @@ -0,0 +1,141 @@ +{ + "version": "30.1.0", + "artifacts": { + "aws-cdk-rds-integ-secret-rotation.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-rds-integ-secret-rotation.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-rds-integ-secret-rotation": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-rds-integ-secret-rotation.template.json", + "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}/3b78e7a70e98ec500faa058ecc14892c94df0ab8d0359ba99718203b67d4a2e6.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-rds-integ-secret-rotation.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-rds-integ-secret-rotation.assets" + ], + "metadata": { + "/aws-cdk-rds-integ-secret-rotation/DbSecurity/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DbSecurity381C2C15" + } + ], + "/aws-cdk-rds-integ-secret-rotation/test-secret/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "testsecretF8BBC644" + } + ], + "/aws-cdk-rds-integ-secret-rotation/test-secret/Attachment/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "testsecretAttachment19AD251F" + } + ], + "/aws-cdk-rds-integ-secret-rotation/test-secret/test-schedule/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "testsecrettestscheduleEA0B5085" + } + ], + "/aws-cdk-rds-integ-secret-rotation/test-secret/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "testsecretPolicyA5D2F46F" + } + ], + "/aws-cdk-rds-integ-secret-rotation/Database/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "DatabaseB269D8BB" + } + ], + "/aws-cdk-rds-integ-secret-rotation/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-rds-integ-secret-rotation/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-rds-integ-secret-rotation" + }, + "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.template.json", + "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": [ + "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.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": [ + "cdkrdsintegsecretrotationDefaultTestDeployAssert9780868B.assets" + ], + "metadata": { + "/cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/tree.json b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/tree.json new file mode 100644 index 0000000000000..324bde72c38a6 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.js.snapshot/tree.json @@ -0,0 +1,406 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-rds-integ-secret-rotation": { + "id": "aws-cdk-rds-integ-secret-rotation", + "path": "aws-cdk-rds-integ-secret-rotation", + "children": { + "DbSecurity": { + "id": "DbSecurity", + "path": "aws-cdk-rds-integ-secret-rotation/DbSecurity", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/DbSecurity/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::KMS::Key", + "aws:cdk:cloudformation:props": { + "keyPolicy": { + "Statement": [ + { + "Action": "kms:*", + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-kms.CfnKey", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-kms.Key", + "version": "0.0.0" + } + }, + "test-secret": { + "id": "test-secret", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::Secret", + "aws:cdk:cloudformation:props": { + "description": { + "Fn::Join": [ + "", + [ + "Generated by the CDK for stack: ", + { + "Ref": "AWS::StackName" + } + ] + ] + }, + "generateSecretString": { + "passwordLength": 30, + "secretStringTemplate": "{\"username\":\"admin\"}", + "generateStringKey": "password", + "excludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.CfnSecret", + "version": "0.0.0" + } + }, + "Attachment": { + "id": "Attachment", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/Attachment", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/Attachment/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::SecretTargetAttachment", + "aws:cdk:cloudformation:props": { + "secretId": { + "Ref": "testsecretF8BBC644" + }, + "targetId": { + "Ref": "DatabaseB269D8BB" + }, + "targetType": "AWS::RDS::DBCluster" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.CfnSecretTargetAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.SecretTargetAttachment", + "version": "0.0.0" + } + }, + "test-schedule": { + "id": "test-schedule", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/test-schedule", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/test-schedule/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::RotationSchedule", + "aws:cdk:cloudformation:props": { + "secretId": { + "Ref": "testsecretF8BBC644" + }, + "hostedRotationLambda": { + "rotationType": "MySQLSingleUser", + "excludeCharacters": " %+~`#$&*()|[]{}:;<>?!'/@\"\\" + }, + "rotationRules": { + "automaticallyAfterDays": 30 + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.CfnRotationSchedule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.RotationSchedule", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/test-secret/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SecretsManager::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourcePolicy": { + "Statement": [ + { + "Action": "secretsmanager:DeleteSecret", + "Effect": "Deny", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": "*" + }, + { + "Action": [ + "secretsmanager:DescribeSecret", + "secretsmanager:GetSecretValue" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + }, + "Service": "ecs-tasks.amazonaws.com" + }, + "Resource": { + "Ref": "testsecretAttachment19AD251F" + } + } + ], + "Version": "2012-10-17" + }, + "secretId": { + "Ref": "testsecretF8BBC644" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.CfnResourcePolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-secretsmanager.ResourcePolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-rds.DatabaseSecret", + "version": "0.0.0" + } + }, + "Database": { + "id": "Database", + "path": "aws-cdk-rds-integ-secret-rotation/Database", + "children": { + "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup": { + "id": "AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "path": "aws-cdk-rds-integ-secret-rotation/Database/AuroraMySqlDatabaseClusterEngineDefaultParameterGroup", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-rds-integ-secret-rotation/Database/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", + "aws:cdk:cloudformation:props": { + "copyTagsToSnapshot": true, + "dbClusterParameterGroupName": "default.aurora-mysql5.7", + "enableHttpEndpoint": true, + "engine": "aurora-mysql", + "engineMode": "serverless", + "kmsKeyId": { + "Fn::GetAtt": [ + "DbSecurity381C2C15", + "Arn" + ] + }, + "masterUsername": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "testsecretF8BBC644" + }, + ":SecretString:username::}}" + ] + ] + }, + "masterUserPassword": { + "Fn::Join": [ + "", + [ + "{{resolve:secretsmanager:", + { + "Ref": "testsecretF8BBC644" + }, + ":SecretString:password::}}" + ] + ] + }, + "storageEncrypted": true, + "vpcSecurityGroupIds": [] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-rds.CfnDBCluster", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-rds.ServerlessCluster", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-rds-integ-secret-rotation/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-rds-integ-secret-rotation/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-rds-integ-secret-rotation": { + "id": "cdk-rds-integ-secret-rotation", + "path": "cdk-rds-integ-secret-rotation", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-rds-integ-secret-rotation/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-rds-integ-secret-rotation/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-rds-integ-secret-rotation/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.ts b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.ts new file mode 100644 index 0000000000000..af00df5d5ce99 --- /dev/null +++ b/packages/@aws-cdk/aws-rds/test/integ.serverless-cluster-secret-rotation.ts @@ -0,0 +1,33 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as kms from '@aws-cdk/aws-kms'; +import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; +import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; +import { Credentials, ServerlessCluster, DatabaseClusterEngine, DatabaseSecret } from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-rds-integ-secret-rotation'); + +const kmsKey = new kms.Key(stack, 'DbSecurity'); +const secret = new DatabaseSecret(stack, 'test-secret', { + username: 'admin', +}); + +const cluster = new ServerlessCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + credentials: Credentials.fromSecret(secret), + storageEncryptionKey: kmsKey, +}); + +secret.addRotationSchedule('test-schedule', { + hostedRotation: secretsmanager.HostedRotation.mysqlSingleUser(), +}); + +cluster.grantDataApiAccess(new iam.AccountRootPrincipal()); +cluster.grantDataApiAccess(new iam.ServicePrincipal('ecs-tasks.amazonaws.com')); + +new IntegTest(app, 'cdk-rds-integ-secret-rotation', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-redshift/package.json b/packages/@aws-cdk/aws-redshift/package.json index eed9d19d1b10c..e3e4f52a79eed 100644 --- a/packages/@aws-cdk/aws-redshift/package.json +++ b/packages/@aws-cdk/aws-redshift/package.json @@ -87,7 +87,7 @@ "@aws-cdk/pkglint": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1", "jsii": "v4.9-next" }, diff --git a/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js b/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js deleted file mode 100644 index 70203dcc42f3f..0000000000000 --- a/packages/@aws-cdk/aws-redshift/test/cluster-reboot.integ.snapshot/asset.7215c88dd3e638d28329d4538b36cdbfb54233a4d972181795814f8b904d1037/outbound.js +++ /dev/null @@ -1,45 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.httpRequest = exports.invokeFunction = exports.startExecution = void 0; -/* istanbul ignore file */ -const https = require("https"); -// eslint-disable-next-line import/no-extraneous-dependencies -const AWS = require("aws-sdk"); -const FRAMEWORK_HANDLER_TIMEOUT = 900000; // 15 minutes -// In order to honor the overall maximum timeout set for the target process, -// the default 2 minutes from AWS SDK has to be overriden: -// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html#httpOptions-property -const awsSdkConfig = { - httpOptions: { timeout: FRAMEWORK_HANDLER_TIMEOUT }, -}; -async function defaultHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, resolve); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -let sfn; -let lambda; -async function defaultStartExecution(req) { - if (!sfn) { - sfn = new AWS.StepFunctions(awsSdkConfig); - } - return sfn.startExecution(req).promise(); -} -async function defaultInvokeFunction(req) { - if (!lambda) { - lambda = new AWS.Lambda(awsSdkConfig); - } - return lambda.invoke(req).promise(); -} -exports.startExecution = defaultStartExecution; -exports.invokeFunction = defaultInvokeFunction; -exports.httpRequest = defaultHttpRequest; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0Ym91bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJvdXRib3VuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwQkFBMEI7QUFDMUIsK0JBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCwrQkFBK0I7QUFJL0IsTUFBTSx5QkFBeUIsR0FBRyxNQUFNLENBQUMsQ0FBQyxhQUFhO0FBRXZELDRFQUE0RTtBQUM1RSwwREFBMEQ7QUFDMUQsMkZBQTJGO0FBQzNGLE1BQU0sWUFBWSxHQUF5QjtJQUN6QyxXQUFXLEVBQUUsRUFBRSxPQUFPLEVBQUUseUJBQXlCLEVBQUU7Q0FDcEQsQ0FBQztBQUVGLEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ25GLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDNUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1NBQ2Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNYO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsSUFBSSxHQUFzQixDQUFDO0FBQzNCLElBQUksTUFBa0IsQ0FBQztBQUV2QixLQUFLLFVBQVUscUJBQXFCLENBQUMsR0FBMEM7SUFDN0UsSUFBSSxDQUFDLEdBQUcsRUFBRTtRQUNSLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDM0M7SUFFRCxPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDM0MsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FBQyxHQUFpQztJQUNwRSxJQUFJLENBQUMsTUFBTSxFQUFFO1FBQ1gsTUFBTSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUN2QztJQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztBQUN0QyxDQUFDO0FBRVUsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxjQUFjLEdBQUcscUJBQXFCLENBQUM7QUFDdkMsUUFBQSxXQUFXLEdBQUcsa0JBQWtCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgQVdTIGZyb20gJ2F3cy1zZGsnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHR5cGUgeyBDb25maWd1cmF0aW9uT3B0aW9ucyB9IGZyb20gJ2F3cy1zZGsvbGliL2NvbmZpZy1iYXNlJztcblxuY29uc3QgRlJBTUVXT1JLX0hBTkRMRVJfVElNRU9VVCA9IDkwMDAwMDsgLy8gMTUgbWludXRlc1xuXG4vLyBJbiBvcmRlciB0byBob25vciB0aGUgb3ZlcmFsbCBtYXhpbXVtIHRpbWVvdXQgc2V0IGZvciB0aGUgdGFyZ2V0IHByb2Nlc3MsXG4vLyB0aGUgZGVmYXVsdCAyIG1pbnV0ZXMgZnJvbSBBV1MgU0RLIGhhcyB0byBiZSBvdmVycmlkZW46XG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvQVdTL0NvbmZpZy5odG1sI2h0dHBPcHRpb25zLXByb3BlcnR5XG5jb25zdCBhd3NTZGtDb25maWc6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge1xuICBodHRwT3B0aW9uczogeyB0aW1lb3V0OiBGUkFNRVdPUktfSEFORExFUl9USU1FT1VUIH0sXG59O1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0SHR0cFJlcXVlc3Qob3B0aW9uczogaHR0cHMuUmVxdWVzdE9wdGlvbnMsIHJlc3BvbnNlQm9keTogc3RyaW5nKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KG9wdGlvbnMsIHJlc29sdmUpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxubGV0IHNmbjogQVdTLlN0ZXBGdW5jdGlvbnM7XG5sZXQgbGFtYmRhOiBBV1MuTGFtYmRhO1xuXG5hc3luYyBmdW5jdGlvbiBkZWZhdWx0U3RhcnRFeGVjdXRpb24ocmVxOiBBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbklucHV0KTogUHJvbWlzZTxBV1MuU3RlcEZ1bmN0aW9ucy5TdGFydEV4ZWN1dGlvbk91dHB1dD4ge1xuICBpZiAoIXNmbikge1xuICAgIHNmbiA9IG5ldyBBV1MuU3RlcEZ1bmN0aW9ucyhhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIHNmbi5zdGFydEV4ZWN1dGlvbihyZXEpLnByb21pc2UoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdEludm9rZUZ1bmN0aW9uKHJlcTogQVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVxdWVzdCk6IFByb21pc2U8QVdTLkxhbWJkYS5JbnZvY2F0aW9uUmVzcG9uc2U+IHtcbiAgaWYgKCFsYW1iZGEpIHtcbiAgICBsYW1iZGEgPSBuZXcgQVdTLkxhbWJkYShhd3NTZGtDb25maWcpO1xuICB9XG5cbiAgcmV0dXJuIGxhbWJkYS5pbnZva2UocmVxKS5wcm9taXNlKCk7XG59XG5cbmV4cG9ydCBsZXQgc3RhcnRFeGVjdXRpb24gPSBkZWZhdWx0U3RhcnRFeGVjdXRpb247XG5leHBvcnQgbGV0IGludm9rZUZ1bmN0aW9uID0gZGVmYXVsdEludm9rZUZ1bmN0aW9uO1xuZXhwb3J0IGxldCBodHRwUmVxdWVzdCA9IGRlZmF1bHRIdHRwUmVxdWVzdDtcbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index 70fe58b64d860..c25d2219a974a 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -85,9 +85,9 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index d1065f07d934c..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.bundle/index.js b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.bundle/index.js new file mode 100644 index 0000000000000..58bcb1ef7f38e --- /dev/null +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.bundle/index.js @@ -0,0 +1,1205 @@ +"use strict"; +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/assertions/providers/lambda-handler/index.ts +var lambda_handler_exports = {}; +__export(lambda_handler_exports, { + handler: () => handler, + isComplete: () => isComplete, + onTimeout: () => onTimeout +}); +module.exports = __toCommonJS(lambda_handler_exports); + +// ../assertions/lib/matcher.ts +var Matcher = class { + /** + * Check whether the provided object is a subtype of the `IMatcher`. + */ + static isMatcher(x) { + return x && x instanceof Matcher; + } +}; +var MatchResult = class { + constructor(target) { + this.failuresHere = /* @__PURE__ */ new Map(); + this.captures = /* @__PURE__ */ new Map(); + this.finalized = false; + this.innerMatchFailures = /* @__PURE__ */ new Map(); + this._hasFailed = false; + this._failCount = 0; + this._cost = 0; + this.target = target; + } + /** + * DEPRECATED + * @deprecated use recordFailure() + */ + push(matcher, path, message) { + return this.recordFailure({ matcher, path, message }); + } + /** + * Record a new failure into this result at a specific path. + */ + recordFailure(failure) { + const failKey = failure.path.join("."); + let list = this.failuresHere.get(failKey); + if (!list) { + list = []; + this.failuresHere.set(failKey, list); + } + this._failCount += 1; + this._cost += failure.cost ?? 1; + list.push(failure); + this._hasFailed = true; + return this; + } + /** Whether the match is a success */ + get isSuccess() { + return !this._hasFailed; + } + /** Does the result contain any failures. If not, the result is a success */ + hasFailed() { + return this._hasFailed; + } + /** The number of failures */ + get failCount() { + return this._failCount; + } + /** The cost of the failures so far */ + get failCost() { + return this._cost; + } + /** + * Compose the results of a previous match as a subtree. + * @param id the id of the parent tree. + */ + compose(id, inner) { + if (inner.hasFailed()) { + this._hasFailed = true; + this._failCount += inner.failCount; + this._cost += inner._cost; + this.innerMatchFailures.set(id, inner); + } + inner.captures.forEach((vals, capture) => { + vals.forEach((value) => this.recordCapture({ capture, value })); + }); + return this; + } + /** + * Prepare the result to be analyzed. + * This API *must* be called prior to analyzing these results. + */ + finished() { + if (this.finalized) { + return this; + } + if (this.failCount === 0) { + this.captures.forEach((vals, cap) => cap._captured.push(...vals)); + } + this.finalized = true; + return this; + } + /** + * Render the failed match in a presentable way + * + * Prefer using `renderMismatch` over this method. It is left for backwards + * compatibility for test suites that expect it, but `renderMismatch()` will + * produce better output. + */ + toHumanStrings() { + const failures = new Array(); + debugger; + recurse(this, []); + return failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at /${r.path.join("/")}`; + return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; + }); + function recurse(x, prefix) { + for (const fail of Array.from(x.failuresHere.values()).flat()) { + failures.push({ + matcher: fail.matcher, + message: fail.message, + path: [...prefix, ...fail.path] + }); + } + for (const [key, inner] of x.innerMatchFailures.entries()) { + recurse(inner, [...prefix, key]); + } + } + } + /** + * Do a deep render of the match result, showing the structure mismatches in context + */ + renderMismatch() { + if (!this.hasFailed()) { + return ""; + } + const parts = new Array(); + const indents = new Array(); + emitFailures(this, ""); + recurse(this); + return moveMarkersToFront(parts.join("").trimEnd()); + function emit(x) { + if (x === void 0) { + debugger; + } + parts.push(x.replace(/\n/g, ` +${indents.join("")}`)); + } + function emitFailures(r, path, scrapSet) { + for (const fail of r.failuresHere.get(path) ?? []) { + emit(`!! ${fail.message} +`); + } + scrapSet == null ? void 0 : scrapSet.delete(path); + } + function recurse(r) { + const remainingFailures = new Set(Array.from(r.failuresHere.keys()).filter((x) => x !== "")); + if (Array.isArray(r.target)) { + indents.push(" "); + emit("[\n"); + for (const [first, i] of enumFirst(range(r.target.length))) { + if (!first) { + emit(",\n"); + } + emitFailures(r, `${i}`, remainingFailures); + const innerMatcher = r.innerMatchFailures.get(`${i}`); + if (innerMatcher) { + emitFailures(innerMatcher, ""); + recurseComparingValues(innerMatcher, r.target[i]); + } else { + emit(renderAbridged(r.target[i])); + } + } + emitRemaining(); + indents.pop(); + emit("\n]"); + return; + } + if (r.target && typeof r.target === "object") { + indents.push(" "); + emit("{\n"); + const keys = Array.from(/* @__PURE__ */ new Set([ + ...Object.keys(r.target), + ...Array.from(remainingFailures) + ])).sort(); + for (const [first, key] of enumFirst(keys)) { + if (!first) { + emit(",\n"); + } + emitFailures(r, key, remainingFailures); + const innerMatcher = r.innerMatchFailures.get(key); + if (innerMatcher) { + emitFailures(innerMatcher, ""); + emit(`${jsonify(key)}: `); + recurseComparingValues(innerMatcher, r.target[key]); + } else { + emit(`${jsonify(key)}: `); + emit(renderAbridged(r.target[key])); + } + } + emitRemaining(); + indents.pop(); + emit("\n}"); + return; + } + emitRemaining(); + emit(jsonify(r.target)); + function emitRemaining() { + if (remainingFailures.size > 0) { + emit("\n"); + } + for (const key of remainingFailures) { + emitFailures(r, key); + } + } + } + function recurseComparingValues(inner, actualValue) { + if (inner.target === actualValue) { + return recurse(inner); + } + emit(renderAbridged(actualValue)); + emit(" <*> "); + recurse(inner); + } + function renderAbridged(x) { + if (Array.isArray(x)) { + switch (x.length) { + case 0: + return "[]"; + case 1: + return `[ ${renderAbridged(x[0])} ]`; + case 2: + if (x.every((e) => ["number", "boolean", "string"].includes(typeof e))) { + return `[ ${x.map(renderAbridged).join(", ")} ]`; + } + return "[ ... ]"; + default: + return "[ ... ]"; + } + } + if (x && typeof x === "object") { + const keys = Object.keys(x); + switch (keys.length) { + case 0: + return "{}"; + case 1: + return `{ ${JSON.stringify(keys[0])}: ${renderAbridged(x[keys[0]])} }`; + default: + return "{ ... }"; + } + } + return jsonify(x); + } + function jsonify(x) { + return JSON.stringify(x) ?? "undefined"; + } + function moveMarkersToFront(x) { + const re = /^(\s+)!!/gm; + return x.replace(re, (_, spaces) => `!!${spaces.substring(0, spaces.length - 2)}`); + } + } + /** + * Record a capture against in this match result. + */ + recordCapture(options) { + let values = this.captures.get(options.capture); + if (values === void 0) { + values = []; + } + values.push(options.value); + this.captures.set(options.capture, values); + } +}; +function* range(n) { + for (let i = 0; i < n; i++) { + yield i; + } +} +function* enumFirst(xs) { + let first = true; + for (const x of xs) { + yield [first, x]; + first = false; + } +} + +// ../assertions/lib/private/matchers/absent.ts +var AbsentMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual !== void 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Received ${actual}, but key should be absent` + }); + } + return result; + } +}; + +// ../assertions/lib/private/sorting.ts +function sortKeyComparator(keyFn) { + return (a, b) => { + const ak = keyFn(a); + const bk = keyFn(b); + for (let i = 0; i < ak.length && i < bk.length; i++) { + const av = ak[i]; + const bv = bk[i]; + let diff = 0; + if (typeof av === "number" && typeof bv === "number") { + diff = av - bv; + } else if (typeof av === "string" && typeof bv === "string") { + diff = av.localeCompare(bv); + } + if (diff !== 0) { + return diff; + } + } + return bk.length - ak.length; + }; +} + +// ../assertions/lib/private/sparse-matrix.ts +var SparseMatrix = class { + constructor() { + this.matrix = /* @__PURE__ */ new Map(); + } + get(row, col) { + var _a; + return (_a = this.matrix.get(row)) == null ? void 0 : _a.get(col); + } + row(row) { + var _a; + return Array.from(((_a = this.matrix.get(row)) == null ? void 0 : _a.entries()) ?? []); + } + set(row, col, value) { + let r = this.matrix.get(row); + if (!r) { + r = /* @__PURE__ */ new Map(); + this.matrix.set(row, r); + } + r.set(col, value); + } +}; + +// ../assertions/lib/private/type.ts +function getType(obj) { + return Array.isArray(obj) ? "array" : typeof obj; +} + +// ../assertions/lib/match.ts +var Match = class { + /** + * Use this matcher in the place of a field's value, if the field must not be present. + */ + static absent() { + return new AbsentMatch("absent"); + } + /** + * Matches the specified pattern with the array found in the same relative path of the target. + * The set of elements (or matchers) must be in the same order as would be found. + * @param pattern the pattern to match + */ + static arrayWith(pattern) { + return new ArrayMatch("arrayWith", pattern); + } + /** + * Matches the specified pattern with the array found in the same relative path of the target. + * The set of elements (or matchers) must match exactly and in order. + * @param pattern the pattern to match + */ + static arrayEquals(pattern) { + return new ArrayMatch("arrayEquals", pattern, { subsequence: false }); + } + /** + * Deep exact matching of the specified pattern to the target. + * @param pattern the pattern to match + */ + static exact(pattern) { + return new LiteralMatch("exact", pattern, { partialObjects: false }); + } + /** + * Matches the specified pattern to an object found in the same relative path of the target. + * The keys and their values (or matchers) must be present in the target but the target can be a superset. + * @param pattern the pattern to match + */ + static objectLike(pattern) { + return new ObjectMatch("objectLike", pattern); + } + /** + * Matches the specified pattern to an object found in the same relative path of the target. + * The keys and their values (or matchers) must match exactly with the target. + * @param pattern the pattern to match + */ + static objectEquals(pattern) { + return new ObjectMatch("objectEquals", pattern, { partial: false }); + } + /** + * Matches any target which does NOT follow the specified pattern. + * @param pattern the pattern to NOT match + */ + static not(pattern) { + return new NotMatch("not", pattern); + } + /** + * Matches any string-encoded JSON and applies the specified pattern after parsing it. + * @param pattern the pattern to match after parsing the encoded JSON. + */ + static serializedJson(pattern) { + return new SerializedJson("serializedJson", pattern); + } + /** + * Matches any non-null value at the target. + */ + static anyValue() { + return new AnyMatch("anyValue"); + } + /** + * Matches targets according to a regular expression + */ + static stringLikeRegexp(pattern) { + return new StringLikeRegexpMatch("stringLikeRegexp", pattern); + } +}; +var LiteralMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partialObjects = options.partialObjects ?? false; + if (Matcher.isMatcher(this.pattern)) { + throw new Error("LiteralMatch cannot directly contain another matcher. Remove the top-level matcher or nest it more deeply."); + } + } + test(actual) { + if (Array.isArray(this.pattern)) { + return new ArrayMatch(this.name, this.pattern, { subsequence: false, partialObjects: this.partialObjects }).test(actual); + } + if (typeof this.pattern === "object") { + return new ObjectMatch(this.name, this.pattern, { partial: this.partialObjects }).test(actual); + } + const result = new MatchResult(actual); + if (typeof this.pattern !== typeof actual) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected type ${typeof this.pattern} but received ${getType(actual)}` + }); + return result; + } + if (actual !== this.pattern) { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected ${this.pattern} but received ${actual}` + }); + } + return result; + } +}; +var ArrayMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.subsequence = options.subsequence ?? true; + this.partialObjects = options.partialObjects ?? false; + } + test(actual) { + if (!Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type array but received ${getType(actual)}` + }); + } + return this.subsequence ? this.testSubsequence(actual) : this.testFullArray(actual); + } + testFullArray(actual) { + const result = new MatchResult(actual); + let i = 0; + for (; i < this.pattern.length && i < actual.length; i++) { + const patternElement = this.pattern[i]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const innerResult = matcher.test(actual[i]); + result.compose(`${i}`, innerResult); + } + if (i < this.pattern.length) { + result.recordFailure({ + matcher: this, + message: `Not enough elements in array (expecting ${this.pattern.length}, got ${actual.length})`, + path: [`${i}`] + }); + } + if (i < actual.length) { + result.recordFailure({ + matcher: this, + message: `Too many elements in array (expecting ${this.pattern.length}, got ${actual.length})`, + path: [`${i}`] + }); + } + return result; + } + testSubsequence(actual) { + const result = new MatchResult(actual); + let patternIdx = 0; + let actualIdx = 0; + const matches = new SparseMatrix(); + while (patternIdx < this.pattern.length && actualIdx < actual.length) { + const patternElement = this.pattern[patternIdx]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const matcherName = matcher.name; + if (matcherName == "absent" || matcherName == "anyValue") { + throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); + } + const innerResult = matcher.test(actual[actualIdx]); + matches.set(patternIdx, actualIdx, innerResult); + actualIdx++; + if (innerResult.isSuccess) { + result.compose(`${actualIdx}`, innerResult); + patternIdx++; + } + } + if (patternIdx < this.pattern.length) { + for (let spi = 0; spi < patternIdx; spi++) { + const foundMatch = matches.row(spi).find(([, r]) => r.isSuccess); + if (!foundMatch) { + continue; + } + const [index] = foundMatch; + result.compose(`${index}`, new MatchResult(actual[index]).recordFailure({ + matcher: this, + message: `arrayWith pattern ${spi} matched here`, + path: [], + cost: 0 + // This is an informational message so it would be unfair to assign it cost + })); + } + const failedMatches = matches.row(patternIdx); + failedMatches.sort(sortKeyComparator(([i, r]) => [r.failCost, i])); + if (failedMatches.length > 0) { + const [index, innerResult] = failedMatches[0]; + result.recordFailure({ + matcher: this, + message: `Could not match arrayWith pattern ${patternIdx}. This is the closest match`, + path: [`${index}`], + cost: 0 + // Informational message + }); + result.compose(`${index}`, innerResult); + } else { + result.recordFailure({ + matcher: this, + message: `Could not match arrayWith pattern ${patternIdx}. No more elements to try`, + path: [`${actual.length}`] + }); + } + } + return result; + } +}; +var ObjectMatch = class extends Matcher { + constructor(name, pattern, options = {}) { + super(); + this.name = name; + this.pattern = pattern; + this.partial = options.partial ?? true; + } + test(actual) { + if (typeof actual !== "object" || Array.isArray(actual)) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected type object but received ${getType(actual)}` + }); + } + const result = new MatchResult(actual); + if (!this.partial) { + for (const a of Object.keys(actual)) { + if (!(a in this.pattern)) { + result.recordFailure({ + matcher: this, + path: [a], + message: `Unexpected key ${a}` + }); + } + } + } + for (const [patternKey, patternVal] of Object.entries(this.pattern)) { + if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { + result.recordFailure({ + matcher: this, + path: [patternKey], + message: `Missing key '${patternKey}'` + }); + continue; + } + const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); + const inner = matcher.test(actual[patternKey]); + result.compose(patternKey, inner); + } + return result; + } +}; +var SerializedJson = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + if (getType(actual) !== "string") { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Expected JSON as a string but found ${getType(actual)}` + }); + } + let parsed; + try { + parsed = JSON.parse(actual); + } catch (err) { + if (err instanceof SyntaxError) { + return new MatchResult(actual).recordFailure({ + matcher: this, + path: [], + message: `Invalid JSON string: ${actual}` + }); + } else { + throw err; + } + } + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(parsed); + if (innerResult.hasFailed()) { + innerResult.recordFailure({ + matcher: this, + path: [], + message: "Encoded JSON value does not match" + }); + } + return innerResult; + } +}; +var NotMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); + const innerResult = matcher.test(actual); + const result = new MatchResult(actual); + if (innerResult.failCount === 0) { + result.recordFailure({ + matcher: this, + path: [], + message: `Found unexpected match: ${JSON.stringify(actual, void 0, 2)}` + }); + } + return result; + } +}; +var AnyMatch = class extends Matcher { + constructor(name) { + super(); + this.name = name; + } + test(actual) { + const result = new MatchResult(actual); + if (actual == null) { + result.recordFailure({ + matcher: this, + path: [], + message: "Expected a value but found none" + }); + } + return result; + } +}; +var StringLikeRegexpMatch = class extends Matcher { + constructor(name, pattern) { + super(); + this.name = name; + this.pattern = pattern; + } + test(actual) { + const result = new MatchResult(actual); + const regex = new RegExp(this.pattern, "gm"); + if (typeof actual !== "string") { + result.recordFailure({ + matcher: this, + path: [], + message: `Expected a string, but got '${typeof actual}'` + }); + } + if (!regex.test(actual)) { + result.recordFailure({ + matcher: this, + path: [], + message: `String '${actual}' did not match pattern '${this.pattern}'` + }); + } + return result; + } +}; + +// lib/assertions/providers/lambda-handler/base.ts +var https = __toESM(require("https")); +var url = __toESM(require("url")); +var AWS = __toESM(require("aws-sdk")); +var CustomResourceHandler = class { + constructor(event, context) { + this.event = event; + this.context = context; + this.timedOut = false; + this.timeout = setTimeout(async () => { + await this.respond({ + status: "FAILED", + reason: "Lambda Function Timeout", + data: this.context.logStreamName + }); + this.timedOut = true; + }, context.getRemainingTimeInMillis() - 1200); + this.event = event; + this.physicalResourceId = extractPhysicalResourceId(event); + } + /** + * Handles executing the custom resource event. If `stateMachineArn` is present + * in the props then trigger the waiter statemachine + */ + async handle() { + try { + if ("stateMachineArn" in this.event.ResourceProperties) { + const req = { + stateMachineArn: this.event.ResourceProperties.stateMachineArn, + name: this.event.RequestId, + input: JSON.stringify(this.event) + }; + await this.startExecution(req); + return; + } else { + const response = await this.processEvent(this.event.ResourceProperties); + return response; + } + } catch (e) { + console.log(e); + throw e; + } finally { + clearTimeout(this.timeout); + } + } + /** + * Handle async requests from the waiter state machine + */ + async handleIsComplete() { + try { + const result = await this.processEvent(this.event.ResourceProperties); + return result; + } catch (e) { + console.log(e); + return; + } finally { + clearTimeout(this.timeout); + } + } + /** + * Start a step function state machine which will wait for the request + * to be successful. + */ + async startExecution(req) { + try { + const sfn = new AWS.StepFunctions(); + await sfn.startExecution(req).promise(); + } finally { + clearTimeout(this.timeout); + } + } + respond(response) { + if (this.timedOut) { + return; + } + const cfResponse = { + Status: response.status, + Reason: response.reason, + PhysicalResourceId: this.physicalResourceId, + StackId: this.event.StackId, + RequestId: this.event.RequestId, + LogicalResourceId: this.event.LogicalResourceId, + NoEcho: false, + Data: response.data + }; + const responseBody = JSON.stringify(cfResponse); + console.log("Responding to CloudFormation", responseBody); + const parsedUrl = url.parse(this.event.ResponseURL); + const requestOptions = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: "PUT", + headers: { "content-type": "", "content-length": responseBody.length } + }; + return new Promise((resolve, reject) => { + try { + const request2 = https.request(requestOptions, resolve); + request2.on("error", reject); + request2.write(responseBody); + request2.end(); + } catch (e) { + reject(e); + } finally { + clearTimeout(this.timeout); + } + }); + } +}; +function extractPhysicalResourceId(event) { + switch (event.RequestType) { + case "Create": + return event.LogicalResourceId; + case "Update": + case "Delete": + return event.PhysicalResourceId; + } +} + +// lib/assertions/providers/lambda-handler/assertion.ts +var AssertionHandler = class extends CustomResourceHandler { + async processEvent(request2) { + let actual = decodeCall(request2.actual); + const expected = decodeCall(request2.expected); + let result; + const matcher = new MatchCreator(expected).getMatcher(); + console.log(`Testing equality between ${JSON.stringify(request2.actual)} and ${JSON.stringify(request2.expected)}`); + const matchResult = matcher.test(actual); + matchResult.finished(); + if (matchResult.hasFailed()) { + result = { + failed: true, + assertion: JSON.stringify({ + status: "fail", + message: matchResult.renderMismatch() + }) + }; + if (request2.failDeployment) { + throw new Error(result.assertion); + } + } else { + result = { + assertion: JSON.stringify({ + status: "success" + }) + }; + } + return result; + } +}; +var MatchCreator = class { + constructor(obj) { + this.parsedObj = { + matcher: obj + }; + } + /** + * Return a Matcher that can be tested against the actual results. + * This will convert the encoded matchers into their corresponding + * assertions matcher. + * + * For example: + * + * ExpectedResult.objectLike({ + * Messages: [{ + * Body: Match.objectLike({ + * Elements: Match.arrayWith([{ Asdf: 3 }]), + * Payload: Match.serializedJson({ key: 'value' }), + * }), + * }], + * }); + * + * Will be encoded as: + * { + * $ObjectLike: { + * Messages: [{ + * Body: { + * $ObjectLike: { + * Elements: { + * $ArrayWith: [{ Asdf: 3 }], + * }, + * Payload: { + * $SerializedJson: { key: 'value' } + * } + * }, + * }, + * }], + * }, + * } + * + * Which can then be parsed by this function. For each key (recursively) + * the parser will check if the value has one of the encoded matchers as a key + * and if so, it will set the value as the Matcher. So, + * + * { + * Body: { + * $ObjectLike: { + * Elements: { + * $ArrayWith: [{ Asdf: 3 }], + * }, + * Payload: { + * $SerializedJson: { key: 'value' } + * } + * }, + * }, + * } + * + * Will be converted to + * { + * Body: Match.objectLike({ + * Elements: Match.arrayWith([{ Asdf: 3 }]), + * Payload: Match.serializedJson({ key: 'value' }), + * }), + * } + */ + getMatcher() { + try { + const final = JSON.parse(JSON.stringify(this.parsedObj), function(_k, v) { + const nested = Object.keys(v)[0]; + switch (nested) { + case "$ArrayWith": + return Match.arrayWith(v[nested]); + case "$ObjectLike": + return Match.objectLike(v[nested]); + case "$StringLike": + return Match.stringLikeRegexp(v[nested]); + case "$SerializedJson": + return Match.serializedJson(v[nested]); + default: + return v; + } + }); + if (Matcher.isMatcher(final.matcher)) { + return final.matcher; + } + return Match.exact(final.matcher); + } catch { + return Match.exact(this.parsedObj.matcher); + } + } +}; +function decodeCall(call) { + if (!call) { + return void 0; + } + try { + const parsed = JSON.parse(call); + return parsed; + } catch (e) { + return call; + } +} + +// lib/assertions/providers/lambda-handler/utils.ts +function decode(object) { + return JSON.parse(JSON.stringify(object), (_k, v) => { + switch (v) { + case "TRUE:BOOLEAN": + return true; + case "FALSE:BOOLEAN": + return false; + default: + return v; + } + }); +} + +// lib/assertions/providers/lambda-handler/sdk.ts +function flatten(object) { + return Object.assign( + {}, + ...function _flatten(child, path = []) { + return [].concat(...Object.keys(child).map((key) => { + let childKey = Buffer.isBuffer(child[key]) ? child[key].toString("utf8") : child[key]; + if (typeof childKey === "string") { + childKey = isJsonString(childKey); + } + return typeof childKey === "object" && childKey !== null ? _flatten(childKey, path.concat([key])) : { [path.concat([key]).join(".")]: childKey }; + })); + }(object) + ); +} +var AwsApiCallHandler = class extends CustomResourceHandler { + async processEvent(request2) { + const AWS2 = require("aws-sdk"); + console.log(`AWS SDK VERSION: ${AWS2.VERSION}`); + if (!Object.prototype.hasOwnProperty.call(AWS2, request2.service)) { + throw Error(`Service ${request2.service} does not exist in AWS SDK version ${AWS2.VERSION}.`); + } + const service = new AWS2[request2.service](); + const response = await service[request2.api](request2.parameters && decode(request2.parameters)).promise(); + console.log(`SDK response received ${JSON.stringify(response)}`); + delete response.ResponseMetadata; + const respond = { + apiCallResponse: response + }; + const flatData = { + ...flatten(respond) + }; + let resp = respond; + if (request2.outputPaths) { + resp = filterKeys(flatData, request2.outputPaths); + } else if (request2.flattenResponse === "true") { + resp = flatData; + } + console.log(`Returning result ${JSON.stringify(resp)}`); + return resp; + } +}; +function filterKeys(object, searchStrings) { + return Object.entries(object).reduce((filteredObject, [key, value]) => { + for (const searchString of searchStrings) { + if (key.startsWith(`apiCallResponse.${searchString}`)) { + filteredObject[key] = value; + } + } + return filteredObject; + }, {}); +} +function isJsonString(value) { + try { + return JSON.parse(value); + } catch { + return value; + } +} + +// lib/assertions/providers/lambda-handler/types.ts +var ASSERT_RESOURCE_TYPE = "Custom::DeployAssert@AssertEquals"; +var SDK_RESOURCE_TYPE_PREFIX = "Custom::DeployAssert@SdkCall"; + +// lib/assertions/providers/lambda-handler/index.ts +async function handler(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); + const provider = createResourceHandler(event, context); + try { + if (event.RequestType === "Delete") { + await provider.respond({ + status: "SUCCESS", + reason: "OK" + }); + return; + } + const result = await provider.handle(); + if ("stateMachineArn" in event.ResourceProperties) { + console.info('Found "stateMachineArn", waiter statemachine started'); + return; + } else if ("expected" in event.ResourceProperties) { + console.info('Found "expected", testing assertions'); + const actualPath = event.ResourceProperties.actualPath; + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + try { + const assertionResult = await assertion.handle(); + await provider.respond({ + status: "SUCCESS", + reason: "OK", + // return both the result of the API call _and_ the assertion results + data: { + ...assertionResult, + ...result + } + }); + return; + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } catch (e) { + await provider.respond({ + status: "FAILED", + reason: e.message ?? "Internal Error" + }); + return; + } + return; +} +async function onTimeout(timeoutEvent) { + const isCompleteRequest = JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage); + const provider = createResourceHandler(isCompleteRequest, standardContext); + await provider.respond({ + status: "FAILED", + reason: "Operation timed out: " + JSON.stringify(isCompleteRequest) + }); +} +async function isComplete(event, context) { + console.log(`Event: ${JSON.stringify({ ...event, ResponseURL: "..." })}`); + const provider = createResourceHandler(event, context); + try { + const result = await provider.handleIsComplete(); + const actualPath = event.ResourceProperties.actualPath; + if (result) { + const actual = actualPath ? result[`apiCallResponse.${actualPath}`] : result.apiCallResponse; + if ("expected" in event.ResourceProperties) { + const assertion = new AssertionHandler({ + ...event, + ResourceProperties: { + ServiceToken: event.ServiceToken, + actual, + expected: event.ResourceProperties.expected + } + }, context); + const assertionResult = await assertion.handleIsComplete(); + if (!(assertionResult == null ? void 0 : assertionResult.failed)) { + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: { + ...assertionResult, + ...result + } + }); + return; + } else { + console.log(`Assertion Failed: ${JSON.stringify(assertionResult)}`); + throw new Error(JSON.stringify(event)); + } + } + await provider.respond({ + status: "SUCCESS", + reason: "OK", + data: result + }); + } else { + console.log("No result"); + throw new Error(JSON.stringify(event)); + } + return; + } catch (e) { + console.log(e); + throw new Error(JSON.stringify(event)); + } +} +function createResourceHandler(event, context) { + if (event.ResourceType.startsWith(SDK_RESOURCE_TYPE_PREFIX)) { + return new AwsApiCallHandler(event, context); + } else if (event.ResourceType.startsWith(ASSERT_RESOURCE_TYPE)) { + return new AssertionHandler(event, context); + } else { + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} +var standardContext = { + getRemainingTimeInMillis: () => 9e4 +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + handler, + isComplete, + onTimeout +}); diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/cdk.out index 145739f539580..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"22.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integ.json index 258cb246cc28d..eca95212c44ed 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "testCases": { "integ-test-bucket-deployments/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.assets.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.assets.json index 4c728fe27d8c8..205d7688474e5 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.assets.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.assets.json @@ -1,20 +1,20 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { - "e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b": { + "73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4": { "source": { - "path": "asset.e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.bundle", + "path": "asset.73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.bundle", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.zip", + "objectKey": "73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "320a35b24ed97136c867ae2541ddd087d6d0ff3502311494d4aa87572b881e91": { + "cb68a9799f1b0a01be938de2628b70716eb6756ab8b00a9cc4e25379b475254e": { "source": { "path": "integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.template.json", "packaging": "file" @@ -22,7 +22,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "320a35b24ed97136c867ae2541ddd087d6d0ff3502311494d4aa87572b881e91.json", + "objectKey": "cb68a9799f1b0a01be938de2628b70716eb6756ab8b00a9cc4e25379b475254e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.template.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.template.json index d9de0017d7da7..8325db2396a0a 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.template.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/integtestbucketdeploymentsDefaultTestDeployAssertCF25A2DF.template.json @@ -18,7 +18,7 @@ } }, "flattenResponse": "false", - "salt": "1671126524996" + "salt": "1677600919513" }, "UpdateReplacePolicy": "Delete", "DeletionPolicy": "Delete" @@ -82,7 +82,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.zip" + "S3Key": "73c20a669c041469f7fc3fc03d574b093b5b97e7c716f76c1e8117e6163e4dc4.zip" }, "Timeout": 120, "Handler": "index.handler", diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/manifest.json index bd74b674f0dd0..c1296996930d5 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "artifacts": { "test-bucket-deployments-2.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/9854d9c205c56719d3e954eb4cf27a828725afdcd6e7e00b7ccecfce1866740f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/5f955b28abc21da07dc33a4cdd724c0f329f3bb14a71217ca89b731e2ab54413.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -484,7 +484,7 @@ "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}/320a35b24ed97136c867ae2541ddd087d6d0ff3502311494d4aa87572b881e91.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/cb68a9799f1b0a01be938de2628b70716eb6756ab8b00a9cc4e25379b475254e.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.assets.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.assets.json index a705c32a9f7c6..d88f37ddc79ed 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.assets.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": { "source": { @@ -79,7 +79,7 @@ } } }, - "9854d9c205c56719d3e954eb4cf27a828725afdcd6e7e00b7ccecfce1866740f": { + "5f955b28abc21da07dc33a4cdd724c0f329f3bb14a71217ca89b731e2ab54413": { "source": { "path": "test-bucket-deployments-2.template.json", "packaging": "file" @@ -87,7 +87,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9854d9c205c56719d3e954eb4cf27a828725afdcd6e7e00b7ccecfce1866740f.json", + "objectKey": "5f955b28abc21da07dc33a4cdd724c0f329f3bb14a71217ca89b731e2ab54413.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.template.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.template.json index 9f8408949492e..159a28e97aee6 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.template.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/test-bucket-deployments-2.template.json @@ -1013,6 +1013,12 @@ "FileSystemId": { "Ref": "BucketDeploymentEFSVPCc8e45d2d82aec23f89c7172e7e6f994ff3d9c444faDE9EC34B" }, + "AccessPointTags": [ + { + "Key": "Name", + "Value": "test-bucket-deployments-2/BucketDeploymentEFS-VPC-c8e45d2d82aec23f89c7172e7e6f994ff3d9c444fa/AccessPoint" + } + ], "PosixUser": { "Gid": "1001", "Uid": "1001" diff --git a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/tree.json index 82f3c333bf0e8..f54637e846602 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/tree.json @@ -1534,6 +1534,12 @@ "fileSystemId": { "Ref": "BucketDeploymentEFSVPCc8e45d2d82aec23f89c7172e7e6f994ff3d9c444faDE9EC34B" }, + "accessPointTags": [ + { + "key": "Name", + "value": "test-bucket-deployments-2/BucketDeploymentEFS-VPC-c8e45d2d82aec23f89c7172e7e6f994ff3d9c444fa/AccessPoint" + } + ], "posixUser": { "uid": "1001", "gid": "1001" @@ -3188,7 +3194,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3226,7 +3232,7 @@ "path": "integ-test-bucket-deployments/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } }, "DeployAssert": { @@ -3246,7 +3252,7 @@ "path": "integ-test-bucket-deployments/DefaultTest/DeployAssert/AwsApiCallS3listObjects/SdkProvider/AssertionsProvider", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } } }, @@ -3318,7 +3324,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -3360,7 +3366,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-s3/README.md b/packages/@aws-cdk/aws-s3/README.md index c435a96eee6bf..05e313b39dfc9 100644 --- a/packages/@aws-cdk/aws-s3/README.md +++ b/packages/@aws-cdk/aws-s3/README.md @@ -1,4 +1,5 @@ # Amazon S3 Construct Library + --- @@ -19,24 +20,24 @@ const bucket = new s3.Bucket(this, 'MyFirstBucket'); `Bucket` constructs expose the following deploy-time attributes: - * `bucketArn` - the ARN of the bucket (i.e. `arn:aws:s3:::bucket_name`) - * `bucketName` - the name of the bucket (i.e. `bucket_name`) - * `bucketWebsiteUrl` - the Website URL of the bucket (i.e. - `http://bucket_name.s3-website-us-west-1.amazonaws.com`) - * `bucketDomainName` - the URL of the bucket (i.e. `bucket_name.s3.amazonaws.com`) - * `bucketDualStackDomainName` - the dual-stack URL of the bucket (i.e. - `bucket_name.s3.dualstack.eu-west-1.amazonaws.com`) - * `bucketRegionalDomainName` - the regional URL of the bucket (i.e. - `bucket_name.s3.eu-west-1.amazonaws.com`) - * `arnForObjects(pattern)` - the ARN of an object or objects within the bucket (i.e. - `arn:aws:s3:::bucket_name/exampleobject.png` or - `arn:aws:s3:::bucket_name/Development/*`) - * `urlForObject(key)` - the HTTP URL of an object within the bucket (i.e. - `https://s3.cn-north-1.amazonaws.com.cn/china-bucket/mykey`) - * `virtualHostedUrlForObject(key)` - the virtual-hosted style HTTP URL of an object - within the bucket (i.e. `https://china-bucket-s3.cn-north-1.amazonaws.com.cn/mykey`) - * `s3UrlForObject(key)` - the S3 URL of an object within the bucket (i.e. - `s3://bucket/mykey`) +- `bucketArn` - the ARN of the bucket (i.e. `arn:aws:s3:::bucket_name`) +- `bucketName` - the name of the bucket (i.e. `bucket_name`) +- `bucketWebsiteUrl` - the Website URL of the bucket (i.e. + `http://bucket_name.s3-website-us-west-1.amazonaws.com`) +- `bucketDomainName` - the URL of the bucket (i.e. `bucket_name.s3.amazonaws.com`) +- `bucketDualStackDomainName` - the dual-stack URL of the bucket (i.e. + `bucket_name.s3.dualstack.eu-west-1.amazonaws.com`) +- `bucketRegionalDomainName` - the regional URL of the bucket (i.e. + `bucket_name.s3.eu-west-1.amazonaws.com`) +- `arnForObjects(pattern)` - the ARN of an object or objects within the bucket (i.e. + `arn:aws:s3:::bucket_name/exampleobject.png` or + `arn:aws:s3:::bucket_name/Development/*`) +- `urlForObject(key)` - the HTTP URL of an object within the bucket (i.e. + `https://s3.cn-north-1.amazonaws.com.cn/china-bucket/mykey`) +- `virtualHostedUrlForObject(key)` - the virtual-hosted style HTTP URL of an object + within the bucket (i.e. `https://china-bucket-s3.cn-north-1.amazonaws.com.cn/mykey`) +- `s3UrlForObject(key)` - the S3 URL of an object within the bucket (i.e. + `s3://bucket/mykey`) ## Encryption @@ -90,11 +91,13 @@ A bucket policy will be automatically created for the bucket upon the first call ```ts const bucket = new s3.Bucket(this, 'MyBucket'); -const result = bucket.addToResourcePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject'], - resources: [bucket.arnForObjects('file.txt')], - principals: [new iam.AccountRootPrincipal()], -})); +const result = bucket.addToResourcePolicy( + new iam.PolicyStatement({ + actions: ['s3:GetObject'], + resources: [bucket.arnForObjects('file.txt')], + principals: [new iam.AccountRootPrincipal()], + }) +); ``` If you try to add a policy statement to an existing bucket, this method will @@ -104,11 +107,13 @@ not do anything: const bucket = s3.Bucket.fromBucketName(this, 'existingBucket', 'bucket-name'); // No policy statement will be added to the resource -const result = bucket.addToResourcePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject'], - resources: [bucket.arnForObjects('file.txt')], - principals: [new iam.AccountRootPrincipal()], -})); +const result = bucket.addToResourcePolicy( + new iam.PolicyStatement({ + actions: ['s3:GetObject'], + resources: [bucket.arnForObjects('file.txt')], + principals: [new iam.AccountRootPrincipal()], + }) +); ``` That's because it's not possible to tell whether the bucket @@ -117,11 +122,13 @@ statements to it. We recommend that you always check the result of the call: ```ts const bucket = new s3.Bucket(this, 'MyBucket'); -const result = bucket.addToResourcePolicy(new iam.PolicyStatement({ - actions: ['s3:GetObject'], - resources: [bucket.arnForObjects('file.txt')], - principals: [new iam.AccountRootPrincipal()], -})); +const result = bucket.addToResourcePolicy( + new iam.PolicyStatement({ + actions: ['s3:GetObject'], + resources: [bucket.arnForObjects('file.txt')], + principals: [new iam.AccountRootPrincipal()], + }) +); if (!result.statementAdded) { // Uh-oh! Someone probably made a mistake here. @@ -166,7 +173,42 @@ const bucket = new s3.Bucket(this, 'Bucket', { To use a bucket in a different stack in the same CDK application, pass the object to the other stack: -[sharing bucket between stacks](test/integ.bucket-sharing.lit.ts) +```ts +/** + * Stack that defines the bucket + */ +class Producer extends cdk.Stack { + public readonly myBucket: s3.Bucket; + + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + + const bucket = new s3.Bucket(this, 'MyBucket', { + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + this.myBucket = bucket; + } +} + +interface ConsumerProps extends cdk.StackProps { + userBucket: s3.IBucket; +} + +/** + * Stack that consumes the bucket + */ +class Consumer extends cdk.Stack { + constructor(scope: cdk.App, id: string, props: ConsumerProps) { + super(scope, id, props); + + const user = new iam.User(this, 'MyUser'); + props.userBucket.grantReadWrite(user); + } +} + +const producer = new Producer(app, 'ProducerStack'); +new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket }); +``` ## Importing existing buckets @@ -181,7 +223,9 @@ const bucket = s3.Bucket.fromBucketAttributes(this, 'ImportedBucket', { }); // now you can just call methods on the bucket -bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(myLambda), {prefix: 'home/myusername/*'}); +bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(myLambda), { + prefix: 'home/myusername/*', +}); ``` Alternatively, short-hand factories are available as `Bucket.fromBucketName` and @@ -190,7 +234,7 @@ name or ARN respectively: ```ts const byName = s3.Bucket.fromBucketName(this, 'BucketByName', 'my-bucket'); -const byArn = s3.Bucket.fromBucketArn(this, 'BucketByArn', 'arn:aws:s3:::my-bucket'); +const byArn = s3.Bucket.fromBucketArn(this, 'BucketByArn', 'arn:aws:s3:::my-bucket'); ``` The bucket's region defaults to the current stack's region, but can also be explicitly set in cases where one of the bucket's @@ -234,9 +278,10 @@ have the `.jpg` suffix are removed from the bucket. ```ts declare const myQueue: sqs.Queue; const bucket = new s3.Bucket(this, 'MyBucket'); -bucket.addEventNotification(s3.EventType.OBJECT_REMOVED, - new s3n.SqsDestination(myQueue), - { prefix: 'foo/', suffix: '.jpg' }); +bucket.addEventNotification(s3.EventType.OBJECT_REMOVED, new s3n.SqsDestination(myQueue), { + prefix: 'foo/', + suffix: '.jpg', +}); ``` Adding notifications on existing buckets: @@ -249,7 +294,7 @@ const bucket = s3.Bucket.fromBucketAttributes(this, 'ImportedBucket', { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SnsDestination(topic)); ``` -When you add an event notification to a bucket, a custom resource is created to +When you add an event notification to a bucket, a custom resource is created to manage the notifications. By default, a new role is created for the Lambda function that implements this feature. If you want to use your own role instead, you should provide it in the `Bucket` constructor: @@ -261,10 +306,10 @@ const bucket = new s3.Bucket(this, 'MyBucket', { }); ``` -Whatever role you provide, the CDK will try to modify it by adding the -permissions from `AWSLambdaBasicExecutionRole` (an AWS managed policy) as well -as the permissions `s3:PutBucketNotification` and `s3:GetBucketNotification`. -If you’re passing an imported role, and you don’t want this to happen, configure +Whatever role you provide, the CDK will try to modify it by adding the +permissions from `AWSLambdaBasicExecutionRole` (an AWS managed policy) as well +as the permissions `s3:PutBucketNotification` and `s3:GetBucketNotification`. +If you’re passing an imported role, and you don’t want this to happen, configure it to be immutable: ```ts @@ -273,11 +318,10 @@ const importedRole = iam.Role.fromRoleArn(this, 'role', 'arn:aws:iam::1234567890 }); ``` -> If you provide an imported immutable role, make sure that it has at least all +> If you provide an imported immutable role, make sure that it has at least all > the permissions mentioned above. Otherwise, the deployment will fail! -[S3 Bucket Notifications]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html - +[s3 bucket notifications]: https://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html ### EventBridge notifications @@ -292,7 +336,7 @@ const bucket = new s3.Bucket(this, 'MyEventBridgeBucket', { }); ``` -[S3 EventBridge notifications]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html +[s3 eventbridge notifications]: https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html ## Block Public Access @@ -439,16 +483,18 @@ Alternatively, you can also define multiple `websiteRoutingRules`, to define com ```ts const bucket = new s3.Bucket(this, 'MyRedirectedBucket', { - websiteRoutingRules: [{ - hostName: 'www.example.com', - httpRedirectCode: '302', - protocol: s3.RedirectProtocol.HTTPS, - replaceKey: s3.ReplaceKey.prefixWith('test/'), - condition: { - httpErrorCodeReturnedEquals: '200', - keyPrefixEquals: 'prefix', + websiteRoutingRules: [ + { + hostName: 'www.example.com', + httpRedirectCode: '302', + protocol: s3.RedirectProtocol.HTTPS, + replaceKey: s3.ReplaceKey.prefixWith('test/'), + condition: { + httpErrorCodeReturnedEquals: '200', + keyPrefixEquals: 'prefix', + }, }, - }], + ], }); ``` @@ -479,7 +525,7 @@ bucket.virtualHostedUrlForObject('objectname', { regional: false }); // Virtual You can use one of following properties to specify the bucket [object Ownership]. -[object Ownership]: https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html +[object ownership]: https://docs.aws.amazon.com/AmazonS3/latest/dev/about-object-ownership.html ### Object writer @@ -516,9 +562,9 @@ new s3.Bucket(this, 'MyBucket', { Some services may not not support log delivery to buckets that have object ownership set to bucket owner enforced, such as [S3 buckets using ACLs](#allowing-access-log-delivery-using-a-bucket-policy-recommended) -or [CloudFront Distributions][CloudFront S3 Bucket]. +or [CloudFront Distributions][cloudfront s3 bucket]. -[CloudFront S3 Bucket]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#AccessLogsBucketAndFileOwnership +[cloudfront s3 bucket]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#AccessLogsBucketAndFileOwnership ## Bucket deletion @@ -539,7 +585,7 @@ const bucket = new s3.Bucket(this, 'MyTempFileBucket', { ``` **Warning** if you have deployed a bucket with `autoDeleteObjects: true`, -switching this to `false` in a CDK version *before* `1.126.0` will lead to +switching this to `false` in a CDK version _before_ `1.126.0` will lead to all objects in the bucket being deleted. Be sure to update your bucket resources by deploying with CDK version `1.126.0` or later **before** switching this value to `false`. @@ -568,15 +614,16 @@ bucket.transferAccelerationUrlForObject('objectname'); ```ts new s3.Bucket(this, 'MyBucket', { - intelligentTieringConfigurations: [{ - name: 'foo', - prefix: 'folder/name', - archiveAccessTierTime: cdk.Duration.days(90), - deepArchiveAccessTierTime: cdk.Duration.days(180), - tags: [{key: 'tagname', value: 'tagvalue'}] - }], + intelligentTieringConfigurations: [ + { + name: 'foo', + prefix: 'folder/name', + archiveAccessTierTime: cdk.Duration.days(90), + deepArchiveAccessTierTime: cdk.Duration.days(180), + tags: [{ key: 'tagname', value: 'tagvalue' }], + }, + ], }); - ``` ## Lifecycle Rule @@ -585,35 +632,41 @@ new s3.Bucket(this, 'MyBucket', { ```ts const bucket = new s3.Bucket(this, 'MyBucket', { - lifecycleRules: [{ - abortIncompleteMultipartUploadAfter: cdk.Duration.minutes(30), - enabled: false, - expiration: cdk.Duration.days(30), - expirationDate: new Date(), - expiredObjectDeleteMarker: false, - id: 'id', - noncurrentVersionExpiration: cdk.Duration.days(30), - - // the properties below are optional - noncurrentVersionsToRetain: 123, - noncurrentVersionTransitions: [{ - storageClass: s3.StorageClass.GLACIER, - transitionAfter: cdk.Duration.days(30), + lifecycleRules: [ + { + abortIncompleteMultipartUploadAfter: cdk.Duration.minutes(30), + enabled: false, + expiration: cdk.Duration.days(30), + expirationDate: new Date(), + expiredObjectDeleteMarker: false, + id: 'id', + noncurrentVersionExpiration: cdk.Duration.days(30), // the properties below are optional noncurrentVersionsToRetain: 123, - }], - objectSizeGreaterThan: 500, - prefix: 'prefix', - objectSizeLessThan: 10000, - transitions: [{ - storageClass: s3.StorageClass.GLACIER, - - // the properties below are optional - transitionAfter: cdk.Duration.days(30), - transitionDate: new Date(), - }], - }] + noncurrentVersionTransitions: [ + { + storageClass: s3.StorageClass.GLACIER, + transitionAfter: cdk.Duration.days(30), + + // the properties below are optional + noncurrentVersionsToRetain: 123, + }, + ], + objectSizeGreaterThan: 500, + prefix: 'prefix', + objectSizeLessThan: 10000, + transitions: [ + { + storageClass: s3.StorageClass.GLACIER, + + // the properties below are optional + transitionAfter: cdk.Duration.days(30), + transitionDate: new Date(), + }, + ], + }, + ], }); ``` @@ -628,7 +681,7 @@ Object Lock can be enabled on an S3 bucket by specifying: ```ts const bucket = new s3.Bucket(this, 'MyBucket', { - objectLockEnabled: true + objectLockEnabled: true, }); ``` @@ -647,5 +700,4 @@ new s3.Bucket(this, 'Bucket1', { new s3.Bucket(this, 'Bucket2', { objectLockDefaultRetention: s3.ObjectLockRetention.compliance(cdk.Duration.days(365)), }); - ``` diff --git a/packages/@aws-cdk/aws-s3/package.json b/packages/@aws-cdk/aws-s3/package.json index b6b9814d26540..3a40c7e810fdc 100644 --- a/packages/@aws-cdk/aws-s3/package.json +++ b/packages/@aws-cdk/aws-s3/package.json @@ -86,7 +86,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf/__entrypoint__.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf/__entrypoint__.js new file mode 100644 index 0000000000000..1e3a3093c1706 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf/__entrypoint__.js @@ -0,0 +1,144 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLFdBQVcsQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFMUQsdURBQXVEO1FBQ3ZELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFcEQsMkJBQTJCO1FBQzNCLE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsQ0FBQztLQUNoRDtJQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ1YsTUFBTSxJQUFJLEdBQWE7WUFDckIsR0FBRyxLQUFLO1lBQ1IsTUFBTSxFQUFFLGdCQUFRLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPO1NBQzFELENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLHlFQUF5RTtZQUN6RSxtRUFBbUU7WUFDbkUsd0VBQXdFO1lBQ3hFLHFFQUFxRTtZQUNyRSxnQ0FBZ0M7WUFDaEMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRTtnQkFDbEMsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsNEdBQTRHLENBQUMsQ0FBQztnQkFDM0gsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGdDQUFnQyxDQUFDO2FBQzVEO2lCQUFNO2dCQUNMLGtFQUFrRTtnQkFDbEUsNkRBQTZEO2dCQUM3RCxnQkFBUSxDQUFDLEdBQUcsQ0FBQyw2REFBNkQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDcEc7U0FDRjtRQUVELG1FQUFtRTtRQUNuRSxNQUFNLGNBQWMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDdEM7QUFDSCxDQUFDO0FBbkRELDBCQW1EQztBQUVELFNBQVMsY0FBYyxDQUNyQixVQUF5RixFQUN6RixrQkFBMEMsRUFBRztJQUU3QyxzRUFBc0U7SUFDdEUsdUJBQXVCO0lBQ3ZCLE1BQU0sa0JBQWtCLEdBQUcsZUFBZSxDQUFDLGtCQUFrQixJQUFJLFVBQVUsQ0FBQyxrQkFBa0IsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO0lBRXZILGtFQUFrRTtJQUNsRSxJQUFJLFVBQVUsQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLGtCQUFrQixLQUFLLFVBQVUsQ0FBQyxrQkFBa0IsRUFBRTtRQUMvRixNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxVQUFVLENBQUMsa0JBQWtCLFNBQVMsZUFBZSxDQUFDLGtCQUFrQixtQkFBbUIsQ0FBQyxDQUFDO0tBQ3RLO0lBRUQsMERBQTBEO0lBQzFELE9BQU87UUFDTCxHQUFHLFVBQVU7UUFDYixHQUFHLGVBQWU7UUFDbEIsa0JBQWtCLEVBQUUsa0JBQWtCO0tBQ3ZDLENBQUM7QUFDSixDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxNQUE0QixFQUFFLEtBQWU7SUFDekUsTUFBTSxJQUFJLEdBQW1EO1FBQzNELE1BQU0sRUFBRSxNQUFNO1FBQ2QsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksTUFBTTtRQUM5QixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSwwQkFBMEI7UUFDMUUsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07UUFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJO0tBQ2pCLENBQUM7SUFFRixnQkFBUSxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUV4RCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sR0FBRyxHQUFHO1FBQ1YsUUFBUSxFQUFFLFNBQVMsQ0FBQyxRQUFRO1FBQzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtLQUN2RSxDQUFDO0lBRUYsTUFBTSxZQUFZLEdBQUc7UUFDbkIsUUFBUSxFQUFFLENBQUM7UUFDWCxLQUFLLEVBQUUsSUFBSTtLQUNaLENBQUM7SUFDRixNQUFNLFdBQVcsQ0FBQyxZQUFZLEVBQUUsZ0JBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDL0UsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ3ZGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWDtJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxHQUFHLE1BQWE7SUFDL0Msc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQVNELFNBQWdCLFdBQVcsQ0FBMEIsT0FBcUIsRUFBRSxFQUE0QjtJQUN0RyxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUssRUFBRSxFQUFFO1FBQ3hCLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDaEMsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUN2QixPQUFPLElBQUksRUFBRTtZQUNYLElBQUk7Z0JBQ0YsT0FBTyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2FBQ3hCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsSUFBSSxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUU7b0JBQ25CLE1BQU0sQ0FBQyxDQUFDO2lCQUNUO2dCQUNELE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDVDtTQUNGO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQWhCRCxrQ0FnQkM7QUFFRCxLQUFLLFVBQVUsS0FBSyxDQUFDLEVBQVU7SUFDN0IsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBodHRwcyBmcm9tICdodHRwcyc7XG5pbXBvcnQgKiBhcyB1cmwgZnJvbSAndXJsJztcblxuLy8gZm9yIHVuaXQgdGVzdHNcbmV4cG9ydCBjb25zdCBleHRlcm5hbCA9IHtcbiAgc2VuZEh0dHBSZXF1ZXN0OiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0LFxuICBsb2c6IGRlZmF1bHRMb2csXG4gIGluY2x1ZGVTdGFja1RyYWNlczogdHJ1ZSxcbiAgdXNlckhhbmRsZXJJbmRleDogJy4vaW5kZXgnLFxufTtcblxuY29uc3QgQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpDUkVBVEVfRkFJTEVEJztcbmNvbnN0IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSID0gJ0FXU0NESzo6Q3VzdG9tUmVzb3VyY2VQcm92aWRlckZyYW1ld29yazo6TUlTU0lOR19QSFlTSUNBTF9JRCc7XG5cbmV4cG9ydCB0eXBlIFJlc3BvbnNlID0gQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIEhhbmRsZXJSZXNwb25zZTtcbmV4cG9ydCB0eXBlIEhhbmRsZXIgPSAoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSA9PiBQcm9taXNlPEhhbmRsZXJSZXNwb25zZSB8IHZvaWQ+O1xuZXhwb3J0IHR5cGUgSGFuZGxlclJlc3BvbnNlID0gdW5kZWZpbmVkIHwge1xuICBEYXRhPzogYW55O1xuICBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmc7XG4gIFJlYXNvbj86IHN0cmluZztcbiAgTm9FY2hvPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkge1xuICBjb25zdCBzYW5pdGl6ZWRFdmVudCA9IHsgLi4uZXZlbnQsIFJlc3BvbnNlVVJMOiAnLi4uJyB9O1xuICBleHRlcm5hbC5sb2coSlNPTi5zdHJpbmdpZnkoc2FuaXRpemVkRXZlbnQsIHVuZGVmaW5lZCwgMikpO1xuXG4gIC8vIGlnbm9yZSBERUxFVEUgZXZlbnQgd2hlbiB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgaXMgdGhlIG1hcmtlciB0aGF0XG4gIC8vIGluZGljYXRlcyB0aGF0IHRoaXMgREVMRVRFIGlzIGEgc3Vic2VxdWVudCBERUxFVEUgdG8gYSBmYWlsZWQgQ1JFQVRFXG4gIC8vIG9wZXJhdGlvbi5cbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgPT09IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSKSB7XG4gICAgZXh0ZXJuYWwubG9nKCdpZ25vcmluZyBERUxFVEUgZXZlbnQgY2F1c2VkIGJ5IGEgZmFpbGVkIENSRUFURSBldmVudCcpO1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgZXZlbnQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLy8gaW52b2tlIHRoZSB1c2VyIGhhbmRsZXIuIHRoaXMgaXMgaW50ZW50aW9uYWxseSBpbnNpZGUgdGhlIHRyeS1jYXRjaCB0b1xuICAgIC8vIGVuc3VyZSB0aGF0IGlmIHRoZXJlIGlzIGFuIGVycm9yIGl0J3MgcmVwb3J0ZWQgYXMgYSBmYWlsdXJlIHRvXG4gICAgLy8gY2xvdWRmb3JtYXRpb24gKG90aGVyd2lzZSBjZm4gd2FpdHMpLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgdXNlckhhbmRsZXI6IEhhbmRsZXIgPSByZXF1aXJlKGV4dGVybmFsLnVzZXJIYW5kbGVySW5kZXgpLmhhbmRsZXI7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdXNlckhhbmRsZXIoc2FuaXRpemVkRXZlbnQsIGNvbnRleHQpO1xuXG4gICAgLy8gdmFsaWRhdGUgdXNlciByZXNwb25zZSBhbmQgY3JlYXRlIHRoZSBjb21iaW5lZCBldmVudFxuICAgIGNvbnN0IHJlc3BvbnNlRXZlbnQgPSByZW5kZXJSZXNwb25zZShldmVudCwgcmVzdWx0KTtcblxuICAgIC8vIHN1Ym1pdCB0byBjZm4gYXMgc3VjY2Vzc1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgcmVzcG9uc2VFdmVudCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zdCByZXNwOiBSZXNwb25zZSA9IHtcbiAgICAgIC4uLmV2ZW50LFxuICAgICAgUmVhc29uOiBleHRlcm5hbC5pbmNsdWRlU3RhY2tUcmFjZXMgPyBlLnN0YWNrIDogZS5tZXNzYWdlLFxuICAgIH07XG5cbiAgICBpZiAoIXJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICAvLyBzcGVjaWFsIGNhc2U6IGlmIENSRUFURSBmYWlscywgd2hpY2ggdXN1YWxseSBpbXBsaWVzLCB3ZSB1c3VhbGx5IGRvbid0XG4gICAgICAvLyBoYXZlIGEgcGh5c2ljYWwgcmVzb3VyY2UgaWQuIGluIHRoaXMgY2FzZSwgdGhlIHN1YnNlcXVlbnQgREVMRVRFXG4gICAgICAvLyBvcGVyYXRpb24gZG9lcyBub3QgaGF2ZSBhbnkgbWVhbmluZywgYW5kIHdpbGwgbGlrZWx5IGZhaWwgYXMgd2VsbC4gdG9cbiAgICAgIC8vIGFkZHJlc3MgdGhpcywgd2UgdXNlIGEgbWFya2VyIHNvIHRoZSBwcm92aWRlciBmcmFtZXdvcmsgY2FuIHNpbXBseVxuICAgICAgLy8gaWdub3JlIHRoZSBzdWJzZXF1ZW50IERFTEVURS5cbiAgICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScpIHtcbiAgICAgICAgZXh0ZXJuYWwubG9nKCdDUkVBVEUgZmFpbGVkLCByZXNwb25kaW5nIHdpdGggYSBtYXJrZXIgcGh5c2ljYWwgcmVzb3VyY2UgaWQgc28gdGhhdCB0aGUgc3Vic2VxdWVudCBERUxFVEUgd2lsbCBiZSBpZ25vcmVkJyk7XG4gICAgICAgIHJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkID0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBvdGhlcndpc2UsIGlmIFBoeXNpY2FsUmVzb3VyY2VJZCBpcyBub3Qgc3BlY2lmaWVkLCBzb21ldGhpbmcgaXNcbiAgICAgICAgLy8gdGVycmlibHkgd3JvbmcgYmVjYXVzZSBhbGwgb3RoZXIgZXZlbnRzIHNob3VsZCBoYXZlIGFuIElELlxuICAgICAgICBleHRlcm5hbC5sb2coYEVSUk9SOiBNYWxmb3JtZWQgZXZlbnQuIFwiUGh5c2ljYWxSZXNvdXJjZUlkXCIgaXMgcmVxdWlyZWQ6ICR7SlNPTi5zdHJpbmdpZnkoZXZlbnQpfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRoaXMgaXMgYW4gYWN0dWFsIGVycm9yLCBmYWlsIHRoZSBhY3Rpdml0eSBhbHRvZ2V0aGVyIGFuZCBleGlzdC5cbiAgICBhd2FpdCBzdWJtaXRSZXNwb25zZSgnRkFJTEVEJywgcmVzcCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVzcG9uc2UoXG4gIGNmblJlcXVlc3Q6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiB7IFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZyB9LFxuICBoYW5kbGVyUmVzcG9uc2U6IHZvaWQgfCBIYW5kbGVyUmVzcG9uc2UgPSB7IH0pOiBSZXNwb25zZSB7XG5cbiAgLy8gaWYgcGh5c2ljYWwgSUQgaXMgbm90IHJldHVybmVkLCB3ZSBoYXZlIHNvbWUgZGVmYXVsdHMgZm9yIHlvdSBiYXNlZFxuICAvLyBvbiB0aGUgcmVxdWVzdCB0eXBlLlxuICBjb25zdCBwaHlzaWNhbFJlc291cmNlSWQgPSBoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUmVxdWVzdElkO1xuXG4gIC8vIGlmIHdlIGFyZSBpbiBERUxFVEUgYW5kIHBoeXNpY2FsIElEIHdhcyBjaGFuZ2VkLCBpdCdzIGFuIGVycm9yLlxuICBpZiAoY2ZuUmVxdWVzdC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScgJiYgcGh5c2ljYWxSZXNvdXJjZUlkICE9PSBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgREVMRVRFOiBjYW5ub3QgY2hhbmdlIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBmcm9tIFwiJHtjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZH1cIiB0byBcIiR7aGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZH1cIiBkdXJpbmcgZGVsZXRpb25gKTtcbiAgfVxuXG4gIC8vIG1lcmdlIHJlcXVlc3QgZXZlbnQgYW5kIHJlc3VsdCBldmVudCAocmVzdWx0IHByZXZhaWxzKS5cbiAgcmV0dXJuIHtcbiAgICAuLi5jZm5SZXF1ZXN0LFxuICAgIC4uLmhhbmRsZXJSZXNwb25zZSxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3VibWl0UmVzcG9uc2Uoc3RhdHVzOiAnU1VDQ0VTUycgfCAnRkFJTEVEJywgZXZlbnQ6IFJlc3BvbnNlKSB7XG4gIGNvbnN0IGpzb246IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2UgPSB7XG4gICAgU3RhdHVzOiBzdGF0dXMsXG4gICAgUmVhc29uOiBldmVudC5SZWFzb24gPz8gc3RhdHVzLFxuICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgfHwgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIsXG4gICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIE5vRWNobzogZXZlbnQuTm9FY2hvLFxuICAgIERhdGE6IGV2ZW50LkRhdGEsXG4gIH07XG5cbiAgZXh0ZXJuYWwubG9nKCdzdWJtaXQgcmVzcG9uc2UgdG8gY2xvdWRmb3JtYXRpb24nLCBqc29uKTtcblxuICBjb25zdCByZXNwb25zZUJvZHkgPSBKU09OLnN0cmluZ2lmeShqc29uKTtcbiAgY29uc3QgcGFyc2VkVXJsID0gdXJsLnBhcnNlKGV2ZW50LlJlc3BvbnNlVVJMKTtcbiAgY29uc3QgcmVxID0ge1xuICAgIGhvc3RuYW1lOiBwYXJzZWRVcmwuaG9zdG5hbWUsXG4gICAgcGF0aDogcGFyc2VkVXJsLnBhdGgsXG4gICAgbWV0aG9kOiAnUFVUJyxcbiAgICBoZWFkZXJzOiB7ICdjb250ZW50LXR5cGUnOiAnJywgJ2NvbnRlbnQtbGVuZ3RoJzogcmVzcG9uc2VCb2R5Lmxlbmd0aCB9LFxuICB9O1xuXG4gIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHtcbiAgICBhdHRlbXB0czogNSxcbiAgICBzbGVlcDogMTAwMCxcbiAgfTtcbiAgYXdhaXQgd2l0aFJldHJpZXMocmV0cnlPcHRpb25zLCBleHRlcm5hbC5zZW5kSHR0cFJlcXVlc3QpKHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlPcHRpb25zIHtcbiAgLyoqIEhvdyBtYW55IHJldHJpZXMgKHdpbGwgYXQgbGVhc3QgdHJ5IG9uY2UpICovXG4gIHJlYWRvbmx5IGF0dGVtcHRzOiBudW1iZXI7XG4gIC8qKiBTbGVlcCBiYXNlLCBpbiBtcyAqL1xuICByZWFkb25seSBzbGVlcDogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aFJldHJpZXM8QSBleHRlbmRzIEFycmF5PGFueT4sIEI+KG9wdGlvbnM6IFJldHJ5T3B0aW9ucywgZm46ICguLi54czogQSkgPT4gUHJvbWlzZTxCPik6ICguLi54czogQSkgPT4gUHJvbWlzZTxCPiB7XG4gIHJldHVybiBhc3luYyAoLi4ueHM6IEEpID0+IHtcbiAgICBsZXQgYXR0ZW1wdHMgPSBvcHRpb25zLmF0dGVtcHRzO1xuICAgIGxldCBtcyA9IG9wdGlvbnMuc2xlZXA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmbiguLi54cyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChhdHRlbXB0cy0tIDw9IDApIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIG1zKSk7XG4gICAgICAgIG1zICo9IDI7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgob2spID0+IHNldFRpbWVvdXQob2ssIG1zKSk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf/index.js similarity index 100% rename from packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.js rename to packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf/index.js diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js new file mode 100644 index 0000000000000..1e3a3093c1706 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/__entrypoint__.js @@ -0,0 +1,144 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withRetries = exports.handler = exports.external = void 0; +const https = require("https"); +const url = require("url"); +// for unit tests +exports.external = { + sendHttpRequest: defaultSendHttpRequest, + log: defaultLog, + includeStackTraces: true, + userHandlerIndex: './index', +}; +const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; +const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; +async function handler(event, context) { + const sanitizedEvent = { ...event, ResponseURL: '...' }; + exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); + // ignore DELETE event when the physical resource ID is the marker that + // indicates that this DELETE is a subsequent DELETE to a failed CREATE + // operation. + if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { + exports.external.log('ignoring DELETE event caused by a failed CREATE event'); + await submitResponse('SUCCESS', event); + return; + } + try { + // invoke the user handler. this is intentionally inside the try-catch to + // ensure that if there is an error it's reported as a failure to + // cloudformation (otherwise cfn waits). + // eslint-disable-next-line @typescript-eslint/no-require-imports + const userHandler = require(exports.external.userHandlerIndex).handler; + const result = await userHandler(sanitizedEvent, context); + // validate user response and create the combined event + const responseEvent = renderResponse(event, result); + // submit to cfn as success + await submitResponse('SUCCESS', responseEvent); + } + catch (e) { + const resp = { + ...event, + Reason: exports.external.includeStackTraces ? e.stack : e.message, + }; + if (!resp.PhysicalResourceId) { + // special case: if CREATE fails, which usually implies, we usually don't + // have a physical resource id. in this case, the subsequent DELETE + // operation does not have any meaning, and will likely fail as well. to + // address this, we use a marker so the provider framework can simply + // ignore the subsequent DELETE. + if (event.RequestType === 'Create') { + exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); + resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; + } + else { + // otherwise, if PhysicalResourceId is not specified, something is + // terribly wrong because all other events should have an ID. + exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); + } + } + // this is an actual error, fail the activity altogether and exist. + await submitResponse('FAILED', resp); + } +} +exports.handler = handler; +function renderResponse(cfnRequest, handlerResponse = {}) { + // if physical ID is not returned, we have some defaults for you based + // on the request type. + const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; + // if we are in DELETE and physical ID was changed, it's an error. + if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { + throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); + } + // merge request event and result event (result prevails). + return { + ...cfnRequest, + ...handlerResponse, + PhysicalResourceId: physicalResourceId, + }; +} +async function submitResponse(status, event) { + const json = { + Status: status, + Reason: event.Reason ?? status, + StackId: event.StackId, + RequestId: event.RequestId, + PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, + LogicalResourceId: event.LogicalResourceId, + NoEcho: event.NoEcho, + Data: event.Data, + }; + exports.external.log('submit response to cloudformation', json); + const responseBody = JSON.stringify(json); + const parsedUrl = url.parse(event.ResponseURL); + const req = { + hostname: parsedUrl.hostname, + path: parsedUrl.path, + method: 'PUT', + headers: { 'content-type': '', 'content-length': responseBody.length }, + }; + const retryOptions = { + attempts: 5, + sleep: 1000, + }; + await withRetries(retryOptions, exports.external.sendHttpRequest)(req, responseBody); +} +async function defaultSendHttpRequest(options, responseBody) { + return new Promise((resolve, reject) => { + try { + const request = https.request(options, _ => resolve()); + request.on('error', reject); + request.write(responseBody); + request.end(); + } + catch (e) { + reject(e); + } + }); +} +function defaultLog(fmt, ...params) { + // eslint-disable-next-line no-console + console.log(fmt, ...params); +} +function withRetries(options, fn) { + return async (...xs) => { + let attempts = options.attempts; + let ms = options.sleep; + while (true) { + try { + return await fn(...xs); + } + catch (e) { + if (attempts-- <= 0) { + throw e; + } + await sleep(Math.floor(Math.random() * ms)); + ms *= 2; + } + } + }; +} +exports.withRetries = withRetries; +async function sleep(ms) { + return new Promise((ok) => setTimeout(ok, ms)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFN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RUFBRSxFQUFFO1FBQ3hCLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDaEMsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztRQUN2QixPQUFPLElBQUksRUFBRTtZQUNYLElBQUk7Z0JBQ0YsT0FBTyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2FBQ3hCO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsSUFBSSxRQUFRLEVBQUUsSUFBSSxDQUFDLEVBQUU7b0JBQ25CLE1BQU0sQ0FBQyxDQUFDO2lCQUNUO2dCQUNELE1BQU0sS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLEVBQUUsSUFBSSxDQUFDLENBQUM7YUFDVDtTQUNGO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQWhCRCxrQ0FnQkM7QUFFRCxLQUFLLFVBQVUsS0FBSyxDQUFDLEVBQVU7SUFDN0IsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ2pELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBodHRwcyBmcm9tICdodHRwcyc7XG5pbXBvcnQgKiBhcyB1cmwgZnJvbSAndXJsJztcblxuLy8gZm9yIHVuaXQgdGVzdHNcbmV4cG9ydCBjb25zdCBleHRlcm5hbCA9IHtcbiAgc2VuZEh0dHBSZXF1ZXN0OiBkZWZhdWx0U2VuZEh0dHBSZXF1ZXN0LFxuICBsb2c6IGRlZmF1bHRMb2csXG4gIGluY2x1ZGVTdGFja1RyYWNlczogdHJ1ZSxcbiAgdXNlckhhbmRsZXJJbmRleDogJy4vaW5kZXgnLFxufTtcblxuY29uc3QgQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpDUkVBVEVfRkFJTEVEJztcbmNvbnN0IE1JU1NJTkdfUEhZU0lDQUxfSURfTUFSS0VSID0gJ0FXU0NESzo6Q3VzdG9tUmVzb3VyY2VQcm92aWRlckZyYW1ld29yazo6TUlTU0lOR19QSFlTSUNBTF9JRCc7XG5cbmV4cG9ydCB0eXBlIFJlc3BvbnNlID0gQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIEhhbmRsZXJSZXNwb25zZTtcbmV4cG9ydCB0eXBlIEhhbmRsZXIgPSAoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSA9PiBQcm9taXNlPEhhbmRsZXJSZXNwb25zZSB8IHZvaWQ+O1xuZXhwb3J0IHR5cGUgSGFuZGxlclJlc3BvbnNlID0gdW5kZWZpbmVkIHwge1xuICBEYXRhPzogYW55O1xuICBQaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmc7XG4gIFJlYXNvbj86IHN0cmluZztcbiAgTm9FY2hvPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKGV2ZW50OiBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBjb250ZXh0OiBBV1NMYW1iZGEuQ29udGV4dCkge1xuICBjb25zdCBzYW5pdGl6ZWRFdmVudCA9IHsgLi4uZXZlbnQsIFJlc3BvbnNlVVJMOiAnLi4uJyB9O1xuICBleHRlcm5hbC5sb2coSlNPTi5zdHJpbmdpZnkoc2FuaXRpemVkRXZlbnQsIHVuZGVmaW5lZCwgMikpO1xuXG4gIC8vIGlnbm9yZSBERUxFVEUgZXZlbnQgd2hlbiB0aGUgcGh5c2ljYWwgcmVzb3VyY2UgSUQgaXMgdGhlIG1hcmtlciB0aGF0XG4gIC8vIGluZGljYXRlcyB0aGF0IHRoaXMgREVMRVRFIGlzIGEgc3Vic2VxdWVudCBERUxFVEUgdG8gYSBmYWlsZWQgQ1JFQVRFXG4gIC8vIG9wZXJhdGlvbi5cbiAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgPT09IENSRUFURV9GQUlMRURfUEhZU0lDQUxfSURfTUFSS0VSKSB7XG4gICAgZXh0ZXJuYWwubG9nKCdpZ25vcmluZyBERUxFVEUgZXZlbnQgY2F1c2VkIGJ5IGEgZmFpbGVkIENSRUFURSBldmVudCcpO1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgZXZlbnQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgLy8gaW52b2tlIHRoZSB1c2VyIGhhbmRsZXIuIHRoaXMgaXMgaW50ZW50aW9uYWxseSBpbnNpZGUgdGhlIHRyeS1jYXRjaCB0b1xuICAgIC8vIGVuc3VyZSB0aGF0IGlmIHRoZXJlIGlzIGFuIGVycm9yIGl0J3MgcmVwb3J0ZWQgYXMgYSBmYWlsdXJlIHRvXG4gICAgLy8gY2xvdWRmb3JtYXRpb24gKG90aGVyd2lzZSBjZm4gd2FpdHMpLlxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgY29uc3QgdXNlckhhbmRsZXI6IEhhbmRsZXIgPSByZXF1aXJlKGV4dGVybmFsLnVzZXJIYW5kbGVySW5kZXgpLmhhbmRsZXI7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdXNlckhhbmRsZXIoc2FuaXRpemVkRXZlbnQsIGNvbnRleHQpO1xuXG4gICAgLy8gdmFsaWRhdGUgdXNlciByZXNwb25zZSBhbmQgY3JlYXRlIHRoZSBjb21iaW5lZCBldmVudFxuICAgIGNvbnN0IHJlc3BvbnNlRXZlbnQgPSByZW5kZXJSZXNwb25zZShldmVudCwgcmVzdWx0KTtcblxuICAgIC8vIHN1Ym1pdCB0byBjZm4gYXMgc3VjY2Vzc1xuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdTVUNDRVNTJywgcmVzcG9uc2VFdmVudCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zdCByZXNwOiBSZXNwb25zZSA9IHtcbiAgICAgIC4uLmV2ZW50LFxuICAgICAgUmVhc29uOiBleHRlcm5hbC5pbmNsdWRlU3RhY2tUcmFjZXMgPyBlLnN0YWNrIDogZS5tZXNzYWdlLFxuICAgIH07XG5cbiAgICBpZiAoIXJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICAvLyBzcGVjaWFsIGNhc2U6IGlmIENSRUFURSBmYWlscywgd2hpY2ggdXN1YWxseSBpbXBsaWVzLCB3ZSB1c3VhbGx5IGRvbid0XG4gICAgICAvLyBoYXZlIGEgcGh5c2ljYWwgcmVzb3VyY2UgaWQuIGluIHRoaXMgY2FzZSwgdGhlIHN1YnNlcXVlbnQgREVMRVRFXG4gICAgICAvLyBvcGVyYXRpb24gZG9lcyBub3QgaGF2ZSBhbnkgbWVhbmluZywgYW5kIHdpbGwgbGlrZWx5IGZhaWwgYXMgd2VsbC4gdG9cbiAgICAgIC8vIGFkZHJlc3MgdGhpcywgd2UgdXNlIGEgbWFya2VyIHNvIHRoZSBwcm92aWRlciBmcmFtZXdvcmsgY2FuIHNpbXBseVxuICAgICAgLy8gaWdub3JlIHRoZSBzdWJzZXF1ZW50IERFTEVURS5cbiAgICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScpIHtcbiAgICAgICAgZXh0ZXJuYWwubG9nKCdDUkVBVEUgZmFpbGVkLCByZXNwb25kaW5nIHdpdGggYSBtYXJrZXIgcGh5c2ljYWwgcmVzb3VyY2UgaWQgc28gdGhhdCB0aGUgc3Vic2VxdWVudCBERUxFVEUgd2lsbCBiZSBpZ25vcmVkJyk7XG4gICAgICAgIHJlc3AuUGh5c2ljYWxSZXNvdXJjZUlkID0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBvdGhlcndpc2UsIGlmIFBoeXNpY2FsUmVzb3VyY2VJZCBpcyBub3Qgc3BlY2lmaWVkLCBzb21ldGhpbmcgaXNcbiAgICAgICAgLy8gdGVycmlibHkgd3JvbmcgYmVjYXVzZSBhbGwgb3RoZXIgZXZlbnRzIHNob3VsZCBoYXZlIGFuIElELlxuICAgICAgICBleHRlcm5hbC5sb2coYEVSUk9SOiBNYWxmb3JtZWQgZXZlbnQuIFwiUGh5c2ljYWxSZXNvdXJjZUlkXCIgaXMgcmVxdWlyZWQ6ICR7SlNPTi5zdHJpbmdpZnkoZXZlbnQpfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHRoaXMgaXMgYW4gYWN0dWFsIGVycm9yLCBmYWlsIHRoZSBhY3Rpdml0eSBhbHRvZ2V0aGVyIGFuZCBleGlzdC5cbiAgICBhd2FpdCBzdWJtaXRSZXNwb25zZSgnRkFJTEVEJywgcmVzcCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVuZGVyUmVzcG9uc2UoXG4gIGNmblJlcXVlc3Q6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQgJiB7IFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZyB9LFxuICBoYW5kbGVyUmVzcG9uc2U6IHZvaWQgfCBIYW5kbGVyUmVzcG9uc2UgPSB7IH0pOiBSZXNwb25zZSB7XG5cbiAgLy8gaWYgcGh5c2ljYWwgSUQgaXMgbm90IHJldHVybmVkLCB3ZSBoYXZlIHNvbWUgZGVmYXVsdHMgZm9yIHlvdSBiYXNlZFxuICAvLyBvbiB0aGUgcmVxdWVzdCB0eXBlLlxuICBjb25zdCBwaHlzaWNhbFJlc291cmNlSWQgPSBoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGNmblJlcXVlc3QuUmVxdWVzdElkO1xuXG4gIC8vIGlmIHdlIGFyZSBpbiBERUxFVEUgYW5kIHBoeXNpY2FsIElEIHdhcyBjaGFuZ2VkLCBpdCdzIGFuIGVycm9yLlxuICBpZiAoY2ZuUmVxdWVzdC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScgJiYgcGh5c2ljYWxSZXNvdXJjZUlkICE9PSBjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgREVMRVRFOiBjYW5ub3QgY2hhbmdlIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBmcm9tIFwiJHtjZm5SZXF1ZXN0LlBoeXNpY2FsUmVzb3VyY2VJZH1cIiB0byBcIiR7aGFuZGxlclJlc3BvbnNlLlBoeXNpY2FsUmVzb3VyY2VJZH1cIiBkdXJpbmcgZGVsZXRpb25gKTtcbiAgfVxuXG4gIC8vIG1lcmdlIHJlcXVlc3QgZXZlbnQgYW5kIHJlc3VsdCBldmVudCAocmVzdWx0IHByZXZhaWxzKS5cbiAgcmV0dXJuIHtcbiAgICAuLi5jZm5SZXF1ZXN0LFxuICAgIC4uLmhhbmRsZXJSZXNwb25zZSxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3VibWl0UmVzcG9uc2Uoc3RhdHVzOiAnU1VDQ0VTUycgfCAnRkFJTEVEJywgZXZlbnQ6IFJlc3BvbnNlKSB7XG4gIGNvbnN0IGpzb246IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2UgPSB7XG4gICAgU3RhdHVzOiBzdGF0dXMsXG4gICAgUmVhc29uOiBldmVudC5SZWFzb24gPz8gc3RhdHVzLFxuICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBldmVudC5QaHlzaWNhbFJlc291cmNlSWQgfHwgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIsXG4gICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIE5vRWNobzogZXZlbnQuTm9FY2hvLFxuICAgIERhdGE6IGV2ZW50LkRhdGEsXG4gIH07XG5cbiAgZXh0ZXJuYWwubG9nKCdzdWJtaXQgcmVzcG9uc2UgdG8gY2xvdWRmb3JtYXRpb24nLCBqc29uKTtcblxuICBjb25zdCByZXNwb25zZUJvZHkgPSBKU09OLnN0cmluZ2lmeShqc29uKTtcbiAgY29uc3QgcGFyc2VkVXJsID0gdXJsLnBhcnNlKGV2ZW50LlJlc3BvbnNlVVJMKTtcbiAgY29uc3QgcmVxID0ge1xuICAgIGhvc3RuYW1lOiBwYXJzZWRVcmwuaG9zdG5hbWUsXG4gICAgcGF0aDogcGFyc2VkVXJsLnBhdGgsXG4gICAgbWV0aG9kOiAnUFVUJyxcbiAgICBoZWFkZXJzOiB7ICdjb250ZW50LXR5cGUnOiAnJywgJ2NvbnRlbnQtbGVuZ3RoJzogcmVzcG9uc2VCb2R5Lmxlbmd0aCB9LFxuICB9O1xuXG4gIGNvbnN0IHJldHJ5T3B0aW9ucyA9IHtcbiAgICBhdHRlbXB0czogNSxcbiAgICBzbGVlcDogMTAwMCxcbiAgfTtcbiAgYXdhaXQgd2l0aFJldHJpZXMocmV0cnlPcHRpb25zLCBleHRlcm5hbC5zZW5kSHR0cFJlcXVlc3QpKHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV0cnlPcHRpb25zIHtcbiAgLyoqIEhvdyBtYW55IHJldHJpZXMgKHdpbGwgYXQgbGVhc3QgdHJ5IG9uY2UpICovXG4gIHJlYWRvbmx5IGF0dGVtcHRzOiBudW1iZXI7XG4gIC8qKiBTbGVlcCBiYXNlLCBpbiBtcyAqL1xuICByZWFkb25seSBzbGVlcDogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2l0aFJldHJpZXM8QSBleHRlbmRzIEFycmF5PGFueT4sIEI+KG9wdGlvbnM6IFJldHJ5T3B0aW9ucywgZm46ICguLi54czogQSkgPT4gUHJvbWlzZTxCPik6ICguLi54czogQSkgPT4gUHJvbWlzZTxCPiB7XG4gIHJldHVybiBhc3luYyAoLi4ueHM6IEEpID0+IHtcbiAgICBsZXQgYXR0ZW1wdHMgPSBvcHRpb25zLmF0dGVtcHRzO1xuICAgIGxldCBtcyA9IG9wdGlvbnMuc2xlZXA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBmbiguLi54cyk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChhdHRlbXB0cy0tIDw9IDApIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHNsZWVwKE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIG1zKSk7XG4gICAgICAgIG1zICo9IDI7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgob2spID0+IHNldFRpbWVvdXQob2ssIG1zKSk7XG59Il19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/index.js similarity index 100% rename from packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.js rename to packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c/index.js diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js deleted file mode 100644 index 9df94382cc74e..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/__entrypoint__.js +++ /dev/null @@ -1,118 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handler = exports.external = void 0; -const https = require("https"); -const url = require("url"); -// for unit tests -exports.external = { - sendHttpRequest: defaultSendHttpRequest, - log: defaultLog, - includeStackTraces: true, - userHandlerIndex: './index', -}; -const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; -const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; -async function handler(event, context) { - const sanitizedEvent = { ...event, ResponseURL: '...' }; - exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); - // ignore DELETE event when the physical resource ID is the marker that - // indicates that this DELETE is a subsequent DELETE to a failed CREATE - // operation. - if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { - exports.external.log('ignoring DELETE event caused by a failed CREATE event'); - await submitResponse('SUCCESS', event); - return; - } - try { - // invoke the user handler. this is intentionally inside the try-catch to - // ensure that if there is an error it's reported as a failure to - // cloudformation (otherwise cfn waits). - // eslint-disable-next-line @typescript-eslint/no-require-imports - const userHandler = require(exports.external.userHandlerIndex).handler; - const result = await userHandler(sanitizedEvent, context); - // validate user response and create the combined event - const responseEvent = renderResponse(event, result); - // submit to cfn as success - await submitResponse('SUCCESS', responseEvent); - } - catch (e) { - const resp = { - ...event, - Reason: exports.external.includeStackTraces ? e.stack : e.message, - }; - if (!resp.PhysicalResourceId) { - // special case: if CREATE fails, which usually implies, we usually don't - // have a physical resource id. in this case, the subsequent DELETE - // operation does not have any meaning, and will likely fail as well. to - // address this, we use a marker so the provider framework can simply - // ignore the subsequent DELETE. - if (event.RequestType === 'Create') { - exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); - resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; - } - else { - // otherwise, if PhysicalResourceId is not specified, something is - // terribly wrong because all other events should have an ID. - exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); - } - } - // this is an actual error, fail the activity altogether and exist. - await submitResponse('FAILED', resp); - } -} -exports.handler = handler; -function renderResponse(cfnRequest, handlerResponse = {}) { - // if physical ID is not returned, we have some defaults for you based - // on the request type. - const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; - // if we are in DELETE and physical ID was changed, it's an error. - if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { - throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); - } - // merge request event and result event (result prevails). - return { - ...cfnRequest, - ...handlerResponse, - PhysicalResourceId: physicalResourceId, - }; -} -async function submitResponse(status, event) { - const json = { - Status: status, - Reason: event.Reason ?? status, - StackId: event.StackId, - RequestId: event.RequestId, - PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, - LogicalResourceId: event.LogicalResourceId, - NoEcho: event.NoEcho, - Data: event.Data, - }; - exports.external.log('submit response to cloudformation', json); - const responseBody = JSON.stringify(json); - const parsedUrl = url.parse(event.ResponseURL); - const req = { - hostname: parsedUrl.hostname, - path: parsedUrl.path, - method: 'PUT', - headers: { 'content-type': '', 'content-length': responseBody.length }, - }; - await exports.external.sendHttpRequest(req, responseBody); -} -async function defaultSendHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, _ => resolve()); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -function defaultLog(fmt, ...params) { - // eslint-disable-next-line no-console - console.log(fmt, ...params); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFN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QzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtLQUN2RSxDQUFDO0lBRUYsTUFBTSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ3ZGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWDtJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxHQUFHLE1BQWE7SUFDL0Msc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnN0IHJlc3A6IFJlc3BvbnNlID0ge1xuICAgICAgLi4uZXZlbnQsXG4gICAgICBSZWFzb246IGV4dGVybmFsLmluY2x1ZGVTdGFja1RyYWNlcyA/IGUuc3RhY2sgOiBlLm1lc3NhZ2UsXG4gICAgfTtcblxuICAgIGlmICghcmVzcC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICAgIC8vIHNwZWNpYWwgY2FzZTogaWYgQ1JFQVRFIGZhaWxzLCB3aGljaCB1c3VhbGx5IGltcGxpZXMsIHdlIHVzdWFsbHkgZG9uJ3RcbiAgICAgIC8vIGhhdmUgYSBwaHlzaWNhbCByZXNvdXJjZSBpZC4gaW4gdGhpcyBjYXNlLCB0aGUgc3Vic2VxdWVudCBERUxFVEVcbiAgICAgIC8vIG9wZXJhdGlvbiBkb2VzIG5vdCBoYXZlIGFueSBtZWFuaW5nLCBhbmQgd2lsbCBsaWtlbHkgZmFpbCBhcyB3ZWxsLiB0b1xuICAgICAgLy8gYWRkcmVzcyB0aGlzLCB3ZSB1c2UgYSBtYXJrZXIgc28gdGhlIHByb3ZpZGVyIGZyYW1ld29yayBjYW4gc2ltcGx5XG4gICAgICAvLyBpZ25vcmUgdGhlIHN1YnNlcXVlbnQgREVMRVRFLlxuICAgICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJykge1xuICAgICAgICBleHRlcm5hbC5sb2coJ0NSRUFURSBmYWlsZWQsIHJlc3BvbmRpbmcgd2l0aCBhIG1hcmtlciBwaHlzaWNhbCByZXNvdXJjZSBpZCBzbyB0aGF0IHRoZSBzdWJzZXF1ZW50IERFTEVURSB3aWxsIGJlIGlnbm9yZWQnKTtcbiAgICAgICAgcmVzcC5QaHlzaWNhbFJlc291cmNlSWQgPSBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgaWYgUGh5c2ljYWxSZXNvdXJjZUlkIGlzIG5vdCBzcGVjaWZpZWQsIHNvbWV0aGluZyBpc1xuICAgICAgICAvLyB0ZXJyaWJseSB3cm9uZyBiZWNhdXNlIGFsbCBvdGhlciBldmVudHMgc2hvdWxkIGhhdmUgYW4gSUQuXG4gICAgICAgIGV4dGVybmFsLmxvZyhgRVJST1I6IE1hbGZvcm1lZCBldmVudC4gXCJQaHlzaWNhbFJlc291cmNlSWRcIiBpcyByZXF1aXJlZDogJHtKU09OLnN0cmluZ2lmeShldmVudCl9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBpcyBhbiBhY3R1YWwgZXJyb3IsIGZhaWwgdGhlIGFjdGl2aXR5IGFsdG9nZXRoZXIgYW5kIGV4aXN0LlxuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdGQUlMRUQnLCByZXNwKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW5kZXJSZXNwb25zZShcbiAgY2ZuUmVxdWVzdDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIHsgUGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nIH0sXG4gIGhhbmRsZXJSZXNwb25zZTogdm9pZCB8IEhhbmRsZXJSZXNwb25zZSA9IHsgfSk6IFJlc3BvbnNlIHtcblxuICAvLyBpZiBwaHlzaWNhbCBJRCBpcyBub3QgcmV0dXJuZWQsIHdlIGhhdmUgc29tZSBkZWZhdWx0cyBmb3IgeW91IGJhc2VkXG4gIC8vIG9uIHRoZSByZXF1ZXN0IHR5cGUuXG4gIGNvbnN0IHBoeXNpY2FsUmVzb3VyY2VJZCA9IGhhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5SZXF1ZXN0SWQ7XG5cbiAgLy8gaWYgd2UgYXJlIGluIERFTEVURSBhbmQgcGh5c2ljYWwgSUQgd2FzIGNoYW5nZWQsIGl0J3MgYW4gZXJyb3IuXG4gIGlmIChjZm5SZXF1ZXN0LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBwaHlzaWNhbFJlc291cmNlSWQgIT09IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBERUxFVEU6IGNhbm5vdCBjaGFuZ2UgdGhlIHBoeXNpY2FsIHJlc291cmNlIElEIGZyb20gXCIke2NmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIHRvIFwiJHtoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIGR1cmluZyBkZWxldGlvbmApO1xuICB9XG5cbiAgLy8gbWVyZ2UgcmVxdWVzdCBldmVudCBhbmQgcmVzdWx0IGV2ZW50IChyZXN1bHQgcHJldmFpbHMpLlxuICByZXR1cm4ge1xuICAgIC4uLmNmblJlcXVlc3QsXG4gICAgLi4uaGFuZGxlclJlc3BvbnNlLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdWJtaXRSZXNwb25zZShzdGF0dXM6ICdTVUNDRVNTJyB8ICdGQUlMRUQnLCBldmVudDogUmVzcG9uc2UpIHtcbiAgY29uc3QganNvbjogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VSZXNwb25zZSA9IHtcbiAgICBTdGF0dXM6IHN0YXR1cyxcbiAgICBSZWFzb246IGV2ZW50LlJlYXNvbiA/PyBzdGF0dXMsXG4gICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICBSZXF1ZXN0SWQ6IGV2ZW50LlJlcXVlc3RJZCxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCB8fCBNSVNTSU5HX1BIWVNJQ0FMX0lEX01BUktFUixcbiAgICBMb2dpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgTm9FY2hvOiBldmVudC5Ob0VjaG8sXG4gICAgRGF0YTogZXZlbnQuRGF0YSxcbiAgfTtcblxuICBleHRlcm5hbC5sb2coJ3N1Ym1pdCByZXNwb25zZSB0byBjbG91ZGZvcm1hdGlvbicsIGpzb24pO1xuXG4gIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KGpzb24pO1xuICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2UoZXZlbnQuUmVzcG9uc2VVUkwpO1xuICBjb25zdCByZXEgPSB7XG4gICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICBwYXRoOiBwYXJzZWRVcmwucGF0aCxcbiAgICBtZXRob2Q6ICdQVVQnLFxuICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiByZXNwb25zZUJvZHkubGVuZ3RoIH0sXG4gIH07XG5cbiAgYXdhaXQgZXh0ZXJuYWwuc2VuZEh0dHBSZXF1ZXN0KHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts deleted file mode 100644 index 3554dc94d4617..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent): Promise; diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts deleted file mode 100644 index 2459d44ab1d18..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26/index.ts +++ /dev/null @@ -1,82 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { S3 } from 'aws-sdk'; - -const AUTO_DELETE_OBJECTS_TAG = 'aws-cdk:auto-delete-objects'; - -const s3 = new S3(); - -export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent) { - switch (event.RequestType) { - case 'Create': - return; - case 'Update': - return onUpdate(event); - case 'Delete': - return onDelete(event.ResourceProperties?.BucketName); - } -} - -async function onUpdate(event: AWSLambda.CloudFormationCustomResourceEvent) { - const updateEvent = event as AWSLambda.CloudFormationCustomResourceUpdateEvent; - const oldBucketName = updateEvent.OldResourceProperties?.BucketName; - const newBucketName = updateEvent.ResourceProperties?.BucketName; - const bucketNameHasChanged = newBucketName != null && oldBucketName != null && newBucketName !== oldBucketName; - - /* If the name of the bucket has changed, CloudFormation will try to delete the bucket - and create a new one with the new name. So we have to delete the contents of the - bucket so that this operation does not fail. */ - if (bucketNameHasChanged) { - return onDelete(oldBucketName); - } -} - -/** - * Recursively delete all items in the bucket - * - * @param bucketName the bucket name - */ -async function emptyBucket(bucketName: string) { - const listedObjects = await s3.listObjectVersions({ Bucket: bucketName }).promise(); - const contents = [...listedObjects.Versions ?? [], ...listedObjects.DeleteMarkers ?? []]; - if (contents.length === 0) { - return; - } - - const records = contents.map((record: any) => ({ Key: record.Key, VersionId: record.VersionId })); - await s3.deleteObjects({ Bucket: bucketName, Delete: { Objects: records } }).promise(); - - if (listedObjects?.IsTruncated) { - await emptyBucket(bucketName); - } -} - -async function onDelete(bucketName?: string) { - if (!bucketName) { - throw new Error('No BucketName was provided.'); - } - if (!await isBucketTaggedForDeletion(bucketName)) { - process.stdout.write(`Bucket does not have '${AUTO_DELETE_OBJECTS_TAG}' tag, skipping cleaning.\n`); - return; - } - try { - await emptyBucket(bucketName); - } catch (e) { - if (e.code !== 'NoSuchBucket') { - throw e; - } - // Bucket doesn't exist. Ignoring - } -} - -/** - * The bucket will only be tagged for deletion if it's being deleted in the same - * deployment as this Custom Resource. - * - * If the Custom Resource is every deleted before the bucket, it must be because - * `autoDeleteObjects` has been switched to false, in which case the tag would have - * been removed before we get to this Delete event. - */ -async function isBucketTaggedForDeletion(bucketName: string) { - const response = await s3.getBucketTagging({ Bucket: bucketName }).promise(); - return response.TagSet.some(tag => tag.Key === AUTO_DELETE_OBJECTS_TAG && tag.Value === 'true'); -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/__entrypoint__.js b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/__entrypoint__.js deleted file mode 100644 index 9df94382cc74e..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/__entrypoint__.js +++ /dev/null @@ -1,118 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.handler = exports.external = void 0; -const https = require("https"); -const url = require("url"); -// for unit tests -exports.external = { - sendHttpRequest: defaultSendHttpRequest, - log: defaultLog, - includeStackTraces: true, - userHandlerIndex: './index', -}; -const CREATE_FAILED_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::CREATE_FAILED'; -const MISSING_PHYSICAL_ID_MARKER = 'AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID'; -async function handler(event, context) { - const sanitizedEvent = { ...event, ResponseURL: '...' }; - exports.external.log(JSON.stringify(sanitizedEvent, undefined, 2)); - // ignore DELETE event when the physical resource ID is the marker that - // indicates that this DELETE is a subsequent DELETE to a failed CREATE - // operation. - if (event.RequestType === 'Delete' && event.PhysicalResourceId === CREATE_FAILED_PHYSICAL_ID_MARKER) { - exports.external.log('ignoring DELETE event caused by a failed CREATE event'); - await submitResponse('SUCCESS', event); - return; - } - try { - // invoke the user handler. this is intentionally inside the try-catch to - // ensure that if there is an error it's reported as a failure to - // cloudformation (otherwise cfn waits). - // eslint-disable-next-line @typescript-eslint/no-require-imports - const userHandler = require(exports.external.userHandlerIndex).handler; - const result = await userHandler(sanitizedEvent, context); - // validate user response and create the combined event - const responseEvent = renderResponse(event, result); - // submit to cfn as success - await submitResponse('SUCCESS', responseEvent); - } - catch (e) { - const resp = { - ...event, - Reason: exports.external.includeStackTraces ? e.stack : e.message, - }; - if (!resp.PhysicalResourceId) { - // special case: if CREATE fails, which usually implies, we usually don't - // have a physical resource id. in this case, the subsequent DELETE - // operation does not have any meaning, and will likely fail as well. to - // address this, we use a marker so the provider framework can simply - // ignore the subsequent DELETE. - if (event.RequestType === 'Create') { - exports.external.log('CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored'); - resp.PhysicalResourceId = CREATE_FAILED_PHYSICAL_ID_MARKER; - } - else { - // otherwise, if PhysicalResourceId is not specified, something is - // terribly wrong because all other events should have an ID. - exports.external.log(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify(event)}`); - } - } - // this is an actual error, fail the activity altogether and exist. - await submitResponse('FAILED', resp); - } -} -exports.handler = handler; -function renderResponse(cfnRequest, handlerResponse = {}) { - // if physical ID is not returned, we have some defaults for you based - // on the request type. - const physicalResourceId = handlerResponse.PhysicalResourceId ?? cfnRequest.PhysicalResourceId ?? cfnRequest.RequestId; - // if we are in DELETE and physical ID was changed, it's an error. - if (cfnRequest.RequestType === 'Delete' && physicalResourceId !== cfnRequest.PhysicalResourceId) { - throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${handlerResponse.PhysicalResourceId}" during deletion`); - } - // merge request event and result event (result prevails). - return { - ...cfnRequest, - ...handlerResponse, - PhysicalResourceId: physicalResourceId, - }; -} -async function submitResponse(status, event) { - const json = { - Status: status, - Reason: event.Reason ?? status, - StackId: event.StackId, - RequestId: event.RequestId, - PhysicalResourceId: event.PhysicalResourceId || MISSING_PHYSICAL_ID_MARKER, - LogicalResourceId: event.LogicalResourceId, - NoEcho: event.NoEcho, - Data: event.Data, - }; - exports.external.log('submit response to cloudformation', json); - const responseBody = JSON.stringify(json); - const parsedUrl = url.parse(event.ResponseURL); - const req = { - hostname: parsedUrl.hostname, - path: parsedUrl.path, - method: 'PUT', - headers: { 'content-type': '', 'content-length': responseBody.length }, - }; - await exports.external.sendHttpRequest(req, responseBody); -} -async function defaultSendHttpRequest(options, responseBody) { - return new Promise((resolve, reject) => { - try { - const request = https.request(options, _ => resolve()); - request.on('error', reject); - request.write(responseBody); - request.end(); - } - catch (e) { - reject(e); - } - }); -} -function defaultLog(fmt, ...params) { - // eslint-disable-next-line no-console - console.log(fmt, ...params); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZWpzLWVudHJ5cG9pbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJub2RlanMtZW50cnlwb2ludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBRTNCLGlCQUFpQjtBQUNKLFFBQUEsUUFBUSxHQUFHO0lBQ3RCLGVBQWUsRUFBRSxzQkFBc0I7SUFDdkMsR0FBRyxFQUFFLFVBQVU7SUFDZixrQkFBa0IsRUFBRSxJQUFJO0lBQ3hCLGdCQUFnQixFQUFFLFNBQVM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sZ0NBQWdDLEdBQUcsd0RBQXdELENBQUM7QUFDbEcsTUFBTSwwQkFBMEIsR0FBRyw4REFBOEQsQ0FBQztBQVczRixLQUFLLFVBQVUsT0FBTyxDQUFDLEtBQWtELEVBQUUsT0FBMEI7SUFDMUcsTUFBTSxjQUFjLEdBQUcsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDeEQsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFM0QsdUVBQXVFO0lBQ3ZFLHVFQUF1RTtJQUN2RSxhQUFhO0lBQ2IsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsa0JBQWtCLEtBQUssZ0NBQWdDLEVBQUU7UUFDbkcsZ0JBQVEsQ0FBQyxHQUFHLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUN0RSxNQUFNLGNBQWMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDdkMsT0FBTztLQUNSO0lBRUQsSUFBSTtRQUNGLHlFQUF5RTtRQUN6RSxpRUFBaUU7UUFDakUsd0NBQXdDO1FBQ3hDLGlFQUFpRTtRQUNqRSxNQUFNLFdBQVcsR0FBWSxPQUFPLENBQUMsZ0JBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN4RSxNQUFN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QzVCLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtRQUNwQixNQUFNLEVBQUUsS0FBSztRQUNiLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLE1BQU0sRUFBRTtLQUN2RSxDQUFDO0lBRUYsTUFBTSxnQkFBUSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDcEQsQ0FBQztBQUVELEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxPQUE2QixFQUFFLFlBQW9CO0lBQ3ZGLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQzVCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDWDtJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQVcsRUFBRSxHQUFHLE1BQWE7SUFDL0Msc0NBQXNDO0lBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIHVybCBmcm9tICd1cmwnO1xuXG4vLyBmb3IgdW5pdCB0ZXN0c1xuZXhwb3J0IGNvbnN0IGV4dGVybmFsID0ge1xuICBzZW5kSHR0cFJlcXVlc3Q6IGRlZmF1bHRTZW5kSHR0cFJlcXVlc3QsXG4gIGxvZzogZGVmYXVsdExvZyxcbiAgaW5jbHVkZVN0YWNrVHJhY2VzOiB0cnVlLFxuICB1c2VySGFuZGxlckluZGV4OiAnLi9pbmRleCcsXG59O1xuXG5jb25zdCBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUiA9ICdBV1NDREs6OkN1c3RvbVJlc291cmNlUHJvdmlkZXJGcmFtZXdvcms6OkNSRUFURV9GQUlMRUQnO1xuY29uc3QgTUlTU0lOR19QSFlTSUNBTF9JRF9NQVJLRVIgPSAnQVdTQ0RLOjpDdXN0b21SZXNvdXJjZVByb3ZpZGVyRnJhbWV3b3JrOjpNSVNTSU5HX1BIWVNJQ0FMX0lEJztcblxuZXhwb3J0IHR5cGUgUmVzcG9uc2UgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgSGFuZGxlclJlc3BvbnNlO1xuZXhwb3J0IHR5cGUgSGFuZGxlciA9IChldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpID0+IFByb21pc2U8SGFuZGxlclJlc3BvbnNlIHwgdm9pZD47XG5leHBvcnQgdHlwZSBIYW5kbGVyUmVzcG9uc2UgPSB1bmRlZmluZWQgfCB7XG4gIERhdGE/OiBhbnk7XG4gIFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgUmVhc29uPzogc3RyaW5nO1xuICBOb0VjaG8/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoZXZlbnQ6IEFXU0xhbWJkYS5DbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlRXZlbnQsIGNvbnRleHQ6IEFXU0xhbWJkYS5Db250ZXh0KSB7XG4gIGNvbnN0IHNhbml0aXplZEV2ZW50ID0geyAuLi5ldmVudCwgUmVzcG9uc2VVUkw6ICcuLi4nIH07XG4gIGV4dGVybmFsLmxvZyhKU09OLnN0cmluZ2lmeShzYW5pdGl6ZWRFdmVudCwgdW5kZWZpbmVkLCAyKSk7XG5cbiAgLy8gaWdub3JlIERFTEVURSBldmVudCB3aGVuIHRoZSBwaHlzaWNhbCByZXNvdXJjZSBJRCBpcyB0aGUgbWFya2VyIHRoYXRcbiAgLy8gaW5kaWNhdGVzIHRoYXQgdGhpcyBERUxFVEUgaXMgYSBzdWJzZXF1ZW50IERFTEVURSB0byBhIGZhaWxlZCBDUkVBVEVcbiAgLy8gb3BlcmF0aW9uLlxuICBpZiAoZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdEZWxldGUnICYmIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCA9PT0gQ1JFQVRFX0ZBSUxFRF9QSFlTSUNBTF9JRF9NQVJLRVIpIHtcbiAgICBleHRlcm5hbC5sb2coJ2lnbm9yaW5nIERFTEVURSBldmVudCBjYXVzZWQgYnkgYSBmYWlsZWQgQ1JFQVRFIGV2ZW50Jyk7XG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCBldmVudCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBpbnZva2UgdGhlIHVzZXIgaGFuZGxlci4gdGhpcyBpcyBpbnRlbnRpb25hbGx5IGluc2lkZSB0aGUgdHJ5LWNhdGNoIHRvXG4gICAgLy8gZW5zdXJlIHRoYXQgaWYgdGhlcmUgaXMgYW4gZXJyb3IgaXQncyByZXBvcnRlZCBhcyBhIGZhaWx1cmUgdG9cbiAgICAvLyBjbG91ZGZvcm1hdGlvbiAob3RoZXJ3aXNlIGNmbiB3YWl0cykuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCB1c2VySGFuZGxlcjogSGFuZGxlciA9IHJlcXVpcmUoZXh0ZXJuYWwudXNlckhhbmRsZXJJbmRleCkuaGFuZGxlcjtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB1c2VySGFuZGxlcihzYW5pdGl6ZWRFdmVudCwgY29udGV4dCk7XG5cbiAgICAvLyB2YWxpZGF0ZSB1c2VyIHJlc3BvbnNlIGFuZCBjcmVhdGUgdGhlIGNvbWJpbmVkIGV2ZW50XG4gICAgY29uc3QgcmVzcG9uc2VFdmVudCA9IHJlbmRlclJlc3BvbnNlKGV2ZW50LCByZXN1bHQpO1xuXG4gICAgLy8gc3VibWl0IHRvIGNmbiBhcyBzdWNjZXNzXG4gICAgYXdhaXQgc3VibWl0UmVzcG9uc2UoJ1NVQ0NFU1MnLCByZXNwb25zZUV2ZW50KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGNvbnN0IHJlc3A6IFJlc3BvbnNlID0ge1xuICAgICAgLi4uZXZlbnQsXG4gICAgICBSZWFzb246IGV4dGVybmFsLmluY2x1ZGVTdGFja1RyYWNlcyA/IGUuc3RhY2sgOiBlLm1lc3NhZ2UsXG4gICAgfTtcblxuICAgIGlmICghcmVzcC5QaHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICAgIC8vIHNwZWNpYWwgY2FzZTogaWYgQ1JFQVRFIGZhaWxzLCB3aGljaCB1c3VhbGx5IGltcGxpZXMsIHdlIHVzdWFsbHkgZG9uJ3RcbiAgICAgIC8vIGhhdmUgYSBwaHlzaWNhbCByZXNvdXJjZSBpZC4gaW4gdGhpcyBjYXNlLCB0aGUgc3Vic2VxdWVudCBERUxFVEVcbiAgICAgIC8vIG9wZXJhdGlvbiBkb2VzIG5vdCBoYXZlIGFueSBtZWFuaW5nLCBhbmQgd2lsbCBsaWtlbHkgZmFpbCBhcyB3ZWxsLiB0b1xuICAgICAgLy8gYWRkcmVzcyB0aGlzLCB3ZSB1c2UgYSBtYXJrZXIgc28gdGhlIHByb3ZpZGVyIGZyYW1ld29yayBjYW4gc2ltcGx5XG4gICAgICAvLyBpZ25vcmUgdGhlIHN1YnNlcXVlbnQgREVMRVRFLlxuICAgICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnQ3JlYXRlJykge1xuICAgICAgICBleHRlcm5hbC5sb2coJ0NSRUFURSBmYWlsZWQsIHJlc3BvbmRpbmcgd2l0aCBhIG1hcmtlciBwaHlzaWNhbCByZXNvdXJjZSBpZCBzbyB0aGF0IHRoZSBzdWJzZXF1ZW50IERFTEVURSB3aWxsIGJlIGlnbm9yZWQnKTtcbiAgICAgICAgcmVzcC5QaHlzaWNhbFJlc291cmNlSWQgPSBDUkVBVEVfRkFJTEVEX1BIWVNJQ0FMX0lEX01BUktFUjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgaWYgUGh5c2ljYWxSZXNvdXJjZUlkIGlzIG5vdCBzcGVjaWZpZWQsIHNvbWV0aGluZyBpc1xuICAgICAgICAvLyB0ZXJyaWJseSB3cm9uZyBiZWNhdXNlIGFsbCBvdGhlciBldmVudHMgc2hvdWxkIGhhdmUgYW4gSUQuXG4gICAgICAgIGV4dGVybmFsLmxvZyhgRVJST1I6IE1hbGZvcm1lZCBldmVudC4gXCJQaHlzaWNhbFJlc291cmNlSWRcIiBpcyByZXF1aXJlZDogJHtKU09OLnN0cmluZ2lmeShldmVudCl9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBpcyBhbiBhY3R1YWwgZXJyb3IsIGZhaWwgdGhlIGFjdGl2aXR5IGFsdG9nZXRoZXIgYW5kIGV4aXN0LlxuICAgIGF3YWl0IHN1Ym1pdFJlc3BvbnNlKCdGQUlMRUQnLCByZXNwKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW5kZXJSZXNwb25zZShcbiAgY2ZuUmVxdWVzdDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCAmIHsgUGh5c2ljYWxSZXNvdXJjZUlkPzogc3RyaW5nIH0sXG4gIGhhbmRsZXJSZXNwb25zZTogdm9pZCB8IEhhbmRsZXJSZXNwb25zZSA9IHsgfSk6IFJlc3BvbnNlIHtcblxuICAvLyBpZiBwaHlzaWNhbCBJRCBpcyBub3QgcmV0dXJuZWQsIHdlIGhhdmUgc29tZSBkZWZhdWx0cyBmb3IgeW91IGJhc2VkXG4gIC8vIG9uIHRoZSByZXF1ZXN0IHR5cGUuXG4gIGNvbnN0IHBoeXNpY2FsUmVzb3VyY2VJZCA9IGhhbmRsZXJSZXNwb25zZS5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5QaHlzaWNhbFJlc291cmNlSWQgPz8gY2ZuUmVxdWVzdC5SZXF1ZXN0SWQ7XG5cbiAgLy8gaWYgd2UgYXJlIGluIERFTEVURSBhbmQgcGh5c2ljYWwgSUQgd2FzIGNoYW5nZWQsIGl0J3MgYW4gZXJyb3IuXG4gIGlmIChjZm5SZXF1ZXN0LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJyAmJiBwaHlzaWNhbFJlc291cmNlSWQgIT09IGNmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBERUxFVEU6IGNhbm5vdCBjaGFuZ2UgdGhlIHBoeXNpY2FsIHJlc291cmNlIElEIGZyb20gXCIke2NmblJlcXVlc3QuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIHRvIFwiJHtoYW5kbGVyUmVzcG9uc2UuUGh5c2ljYWxSZXNvdXJjZUlkfVwiIGR1cmluZyBkZWxldGlvbmApO1xuICB9XG5cbiAgLy8gbWVyZ2UgcmVxdWVzdCBldmVudCBhbmQgcmVzdWx0IGV2ZW50IChyZXN1bHQgcHJldmFpbHMpLlxuICByZXR1cm4ge1xuICAgIC4uLmNmblJlcXVlc3QsXG4gICAgLi4uaGFuZGxlclJlc3BvbnNlLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBzdWJtaXRSZXNwb25zZShzdGF0dXM6ICdTVUNDRVNTJyB8ICdGQUlMRUQnLCBldmVudDogUmVzcG9uc2UpIHtcbiAgY29uc3QganNvbjogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VSZXNwb25zZSA9IHtcbiAgICBTdGF0dXM6IHN0YXR1cyxcbiAgICBSZWFzb246IGV2ZW50LlJlYXNvbiA/PyBzdGF0dXMsXG4gICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICBSZXF1ZXN0SWQ6IGV2ZW50LlJlcXVlc3RJZCxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCB8fCBNSVNTSU5HX1BIWVNJQ0FMX0lEX01BUktFUixcbiAgICBMb2dpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgTm9FY2hvOiBldmVudC5Ob0VjaG8sXG4gICAgRGF0YTogZXZlbnQuRGF0YSxcbiAgfTtcblxuICBleHRlcm5hbC5sb2coJ3N1Ym1pdCByZXNwb25zZSB0byBjbG91ZGZvcm1hdGlvbicsIGpzb24pO1xuXG4gIGNvbnN0IHJlc3BvbnNlQm9keSA9IEpTT04uc3RyaW5naWZ5KGpzb24pO1xuICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2UoZXZlbnQuUmVzcG9uc2VVUkwpO1xuICBjb25zdCByZXEgPSB7XG4gICAgaG9zdG5hbWU6IHBhcnNlZFVybC5ob3N0bmFtZSxcbiAgICBwYXRoOiBwYXJzZWRVcmwucGF0aCxcbiAgICBtZXRob2Q6ICdQVVQnLFxuICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiByZXNwb25zZUJvZHkubGVuZ3RoIH0sXG4gIH07XG5cbiAgYXdhaXQgZXh0ZXJuYWwuc2VuZEh0dHBSZXF1ZXN0KHJlcSwgcmVzcG9uc2VCb2R5KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVmYXVsdFNlbmRIdHRwUmVxdWVzdChvcHRpb25zOiBodHRwcy5SZXF1ZXN0T3B0aW9ucywgcmVzcG9uc2VCb2R5OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLnJlcXVlc3Qob3B0aW9ucywgXyA9PiByZXNvbHZlKCkpO1xuICAgICAgcmVxdWVzdC5vbignZXJyb3InLCByZWplY3QpO1xuICAgICAgcmVxdWVzdC53cml0ZShyZXNwb25zZUJvZHkpO1xuICAgICAgcmVxdWVzdC5lbmQoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdExvZyhmbXQ6IHN0cmluZywgLi4ucGFyYW1zOiBhbnlbXSkge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhmbXQsIC4uLnBhcmFtcyk7XG59XG4iXX0= \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.d.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.d.ts deleted file mode 100644 index 3554dc94d4617..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent): Promise; diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.ts deleted file mode 100644 index 4a392db00cb66..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import { S3 } from 'aws-sdk'; - -const s3 = new S3(); - -export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent): Promise { - switch (event.RequestType) { - case 'Create': - if (event.ResourceProperties.Fail) { - throw new Error('Failing on request!'); - } - const bucketName = event.ResourceProperties.BucketName; - if (!bucketName) { - throw new Error('Missing BucketName'); - } - return putObjects(bucketName); - case 'Update': - case 'Delete': - return; - } -} - -async function putObjects(bucketName: string, n = 5) { - // Put n objects in parallel - await Promise.all([...Array(n).keys()] - .map(key => s3.putObject({ - Bucket: bucketName, - Key: `Key${key}`, - Body: `Body${key}`, - }).promise())); -} diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.assets.json index 47dcdbf3ac082..b89707c1bbeae 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.assets.json @@ -1,33 +1,33 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { - "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26": { + "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": { "source": { - "path": "asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26", + "path": "asset.33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip", + "objectKey": "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12": { + "01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf": { "source": { - "path": "asset.e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12", + "path": "asset.01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12.zip", + "objectKey": "01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "34588b22066351ec4599612a9503dbbce052c535da98310bc64dda1d3fcc5b3f": { + "90947b61ca4c7d99edb9187a285712c5d12e38ed13467bf721afe3b08c325877": { "source": { "path": "cdk-s3-bucket-auto-delete-objects.template.json", "packaging": "file" @@ -35,7 +35,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "34588b22066351ec4599612a9503dbbce052c535da98310bc64dda1d3fcc5b3f.json", + "objectKey": "90947b61ca4c7d99edb9187a285712c5d12e38ed13467bf721afe3b08c325877.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json index adfe920639ba7..c1b94ee7f40ac 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk-s3-bucket-auto-delete-objects.template.json @@ -112,7 +112,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip" + "S3Key": "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c.zip" }, "Timeout": 900, "MemorySize": 128, @@ -198,7 +198,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "e9c68cf1f45c13541846ac21c968ae404003e58f772e7c54163c0980d8123e12.zip" + "S3Key": "01eedf6f2e5aae25db3514bf9c65e042c4365726d7876ad9f10d35b65f5500cf.zip" }, "Timeout": 900, "MemorySize": 128, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets.json new file mode 100644 index 0000000000000..684eab00c908f --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.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/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.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/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/integ.json index 38516cf9c396b..5a1661f5c8d31 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket-auto-delete-objects": { + "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest": { "stacks": [ "cdk-s3-bucket-auto-delete-objects" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json index 1221080a9fc4c..7203978a6d570 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "cdk-s3-bucket-auto-delete-objects.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/34588b22066351ec4599612a9503dbbce052c535da98310bc64dda1d3fcc5b3f.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/90947b61ca4c7d99edb9187a285712c5d12e38ed13467bf721afe3b08c325877.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -101,6 +95,59 @@ ] }, "displayName": "cdk-s3-bucket-auto-delete-objects" + }, + "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.template.json", + "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": [ + "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.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": [ + "cdkintegs3bucketautodeleteobjectsDefaultTestDeployAssert7EEB3F44.assets" + ], + "metadata": { + "/cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json index 9aae0df949919..7b820afa82fe1 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "cdk-s3-bucket-auto-delete-objects": { "id": "cdk-s3-bucket-auto-delete-objects", "path": "cdk-s3-bucket-auto-delete-objects", @@ -116,14 +108,14 @@ "id": "Default", "path": "cdk-s3-bucket-auto-delete-objects/Bucket/AutoDeleteObjectsCustomResource/Default", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" } } }, @@ -140,30 +132,30 @@ "id": "Staging", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3AutoDeleteObjectsCustomResourceProvider/Staging", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "Role": { "id": "Role", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3AutoDeleteObjectsCustomResourceProvider/Role", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } }, "Handler": { "id": "Handler", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3AutoDeleteObjectsCustomResourceProvider/Handler", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResourceProvider", + "version": "0.0.0" } }, "Custom::S3PutObjectsCustomResourceProvider": { @@ -174,30 +166,30 @@ "id": "Staging", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3PutObjectsCustomResourceProvider/Staging", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" } }, "Role": { "id": "Role", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3PutObjectsCustomResourceProvider/Role", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } }, "Handler": { "id": "Handler", "path": "cdk-s3-bucket-auto-delete-objects/Custom::S3PutObjectsCustomResourceProvider/Handler", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CustomResourceProvider", + "version": "0.0.0" } }, "PutObjectsCustomResource": { @@ -207,27 +199,105 @@ "Default": { "id": "Default", "path": "cdk-s3-bucket-auto-delete-objects/PutObjectsCustomResource/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-s3-bucket-auto-delete-objects/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-s3-bucket-auto-delete-objects/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-s3-bucket-auto-delete-objects": { + "id": "cdk-integ-s3-bucket-auto-delete-objects", + "path": "cdk-integ-s3-bucket-auto-delete-objects", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-s3-bucket-auto-delete-objects/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.ts index 1ecd9ae6f8dea..ba27583d3ce86 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-auto-delete-objects.ts @@ -1,5 +1,6 @@ import * as path from 'path'; import { App, CustomResource, CustomResourceProvider, CustomResourceProviderRuntime, RemovalPolicy, Stack, StackProps } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import { Construct } from 'constructs'; import * as s3 from '../lib'; @@ -35,5 +36,7 @@ class TestStack extends Stack { } const app = new App(); -new TestStack(app, 'cdk-s3-bucket-auto-delete-objects'); -app.synth(); + +new IntegTest(app, 'cdk-integ-s3-bucket-auto-delete-objects', { + testCases: [new TestStack(app, 'cdk-s3-bucket-auto-delete-objects')], +}); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/aws-cdk-s3.assets.json index e1a9fa328274b..e70230520755e 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "d58564e550578b842d263813989612c57f0be57bbe638c5d041fa759b57db7c1": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets.json new file mode 100644 index 0000000000000..88b918d331bd8 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.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/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.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/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/integ.json index 716c4104c85ec..d72f7b902a999 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket-grantdelete-kms": { + "cdk-integ-s3-grant-delete-kms/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/manifest.json index 6c0a90b296a12..c199d0d8a92f2 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -77,6 +71,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.template.json", + "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": [ + "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.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": [ + "cdkintegs3grantdeletekmsDefaultTestDeployAssertEC0923BA.assets" + ], + "metadata": { + "/cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/tree.json index ae389a29bb402..f7cd1fdddc619 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -178,17 +170,95 @@ "fqn": "@aws-cdk/aws-s3.Bucket", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-s3-grant-delete-kms": { + "id": "cdk-integ-s3-grant-delete-kms", + "path": "cdk-integ-s3-grant-delete-kms", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-s3-grant-delete-kms/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-s3-grant-delete-kms/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-s3-grant-delete-kms/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts index c3ba55f721599..8faecb66bb2bf 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-grantdelete-kms.ts @@ -2,6 +2,7 @@ import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; const app = new cdk.App(); @@ -18,4 +19,6 @@ const bucket = new s3.Bucket(stack, 'MyBucket', { // when bucket.grantDelete(deleter); -app.synth(); \ No newline at end of file +new IntegTest(app, 'cdk-integ-s3-grant-delete-kms', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json index 158be521a0100..f7aac2f276aab 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-delivery.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-delivery.assets.json index 3f6f0869c8925..cd7238bd28a3f 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-delivery.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-delivery.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-target.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-target.assets.json index d1dfc1490358c..3c941d80b4b9b 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-target.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/aws-cdk-s3-access-logs-target.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "33e2651435a0d472a75c1e033c9832b21321d9e56711926b04c5705e5f63874c": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/cdk.out index 145739f539580..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"22.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/integ.json index 67c79ca839b8c..8accb4d457ca4 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "testCases": { "ServerAccessLogsImportTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/manifest.json index 5d197f4fd7011..acad90361aea3 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-s3-access-logs-target.assets": { "type": "cdk:asset-manifest", diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/tree.json index a560510a2ffa3..ebd61577c5fe9 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.js.snapshot/tree.json @@ -251,7 +251,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -528,7 +528,7 @@ "path": "ServerAccessLogsImportTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } }, "DeployAssert": { @@ -574,7 +574,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.ts index 3039a216b4489..612fd2e587112 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-import-server-access-logs.ts @@ -34,5 +34,3 @@ new s3.Bucket(sourceBucketStack, 'SourceBucket', { new integ.IntegTest(app, 'ServerAccessLogsImportTest', { testCases: [sourceBucketStack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/aws-cdk-s3.assets.json index 48832f621b5ce..03d30c13f3f15 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "adf3c2f8262352f66ed192a1df02462d836f377c0853aa48562db222c63ca4fe": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets.json new file mode 100644 index 0000000000000..56fdf483341e3 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.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/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/cdkintegintelligenttieringDefaultTestDeployAssertCA983383.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/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/integ.json index ff5cf6fc5aaa5..4a3bc5434b7f4 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket-intelligent-tiering": { + "cdk-integ-intelligent-tiering/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-intelligent-tiering/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegintelligenttieringDefaultTestDeployAssertCA983383" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/manifest.json index e6a63b1756962..173ff55816481 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -59,6 +53,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegintelligenttieringDefaultTestDeployAssertCA983383": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.template.json", + "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": [ + "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.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": [ + "cdkintegintelligenttieringDefaultTestDeployAssertCA983383.assets" + ], + "metadata": { + "/cdk-integ-intelligent-tiering/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-intelligent-tiering/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-intelligent-tiering/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/tree.json index f46944949aba4..961474f149d9e 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -61,17 +53,95 @@ "fqn": "@aws-cdk/aws-s3.Bucket", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-intelligent-tiering": { + "id": "cdk-integ-intelligent-tiering", + "path": "cdk-integ-intelligent-tiering", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-intelligent-tiering/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-intelligent-tiering/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-intelligent-tiering/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-intelligent-tiering/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-intelligent-tiering/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.ts index a39b06dd42a55..1419e1d0e0b64 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-intelligent-tiering.ts @@ -1,4 +1,5 @@ import { App, Duration, Stack } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib/index'; const app = new App(); @@ -16,4 +17,6 @@ new s3.Bucket(stack, 'MyBucket', { }); -app.synth(); +new IntegTest(app, 'cdk-integ-intelligent-tiering', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/aws-cdk-s3.assets.json index 95a28b2cae4ee..cea7b54847759 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "a1456aedf39cb4f8db9c2e9de34250499617d8dd23f8210ef251f35870e1ac24": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json new file mode 100644 index 0000000000000..0ec925d5129e3 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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/aws-s3/test/integ.bucket-inventory.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/integ.json index 83852196c4971..e31192fcf4b7b 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket-inventory": { + "cdk-integ-bucket-inventory/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/manifest.json index 49323b3b36b2a..984beb3d402bb 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -83,6 +77,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json", + "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": [ + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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": [ + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets" + ], + "metadata": { + "/cdk-integ-bucket-inventory/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-bucket-inventory/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/tree.json index f3913165054a0..09a6c29d35738 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -255,17 +247,95 @@ "fqn": "@aws-cdk/aws-s3.Bucket", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-bucket-inventory": { + "id": "cdk-integ-bucket-inventory", + "path": "cdk-integ-bucket-inventory", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-bucket-inventory/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-bucket-inventory/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.ts index 3bea814804e87..090a633c8ebcd 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-inventory.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; const app = new cdk.App(); @@ -34,4 +35,6 @@ myBucket.addInventory({ }, }); -app.synth(); +new IntegTest(app, 'cdk-integ-bucket-inventory', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json index 76ee419f6b0f1..f7aac2f276aab 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/ServerAccessLogsImportTestDefaultTestDeployAssert076DA7F5.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/aws-cdk-s3-bucket-object-lock.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/aws-cdk-s3-bucket-object-lock.assets.json index 5c3ec41a3c2da..2633542c847ef 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/aws-cdk-s3-bucket-object-lock.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/aws-cdk-s3-bucket-object-lock.assets.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "files": { "e7897599241ca9562999cb8666f011365be1fbf7f990cfea3947f6026fd8fbb9": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/cdk.out index d8b441d447f8a..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"29.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/integ.json index 52345f6fc37d6..31f4d6f15be26 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "testCases": { "ServerAccessLogsImportTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/manifest.json index a9877309176d5..cb5afd444bba9 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "29.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-s3-bucket-object-lock.assets": { "type": "cdk:asset-manifest", diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/tree.json index 14e8a242e087e..dad95d997c9c0 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.js.snapshot/tree.json @@ -100,7 +100,7 @@ "path": "ServerAccessLogsImportTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.216" + "version": "10.1.252" } }, "DeployAssert": { @@ -146,7 +146,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.216" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.ts index 72434a129e426..60b267d682963 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-object-lock.ts @@ -17,5 +17,3 @@ new s3.Bucket(stack, 'ObjectLockWithRetentionBucket', { new integ.IntegTest(app, 'ServerAccessLogsImportTest', { testCases: [stack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.assets.json new file mode 100644 index 0000000000000..a0bbed1c1beda --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "8256310f1a5d004f222c2df04da2c9bcf7d0e1416fc0c2f07ab472f9eb7858e3": { + "source": { + "path": "ConsumerStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "8256310f1a5d004f222c2df04da2c9bcf7d0e1416fc0c2f07ab472f9eb7858e3.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/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ConsumerStack.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.template.json similarity index 58% rename from packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ConsumerStack.template.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.template.json index 88e399876949e..906df6ecc3ff8 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ConsumerStack.template.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ConsumerStack.template.json @@ -50,5 +50,39 @@ ] } } + }, + "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/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.assets.json new file mode 100644 index 0000000000000..094284cad5536 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "72d18a5cfa63befafc29d9feb111797e3e5a8d80dd2005e1a2c81bc6dd6593ea": { + "source": { + "path": "ProducerStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "72d18a5cfa63befafc29d9feb111797e3e5a8d80dd2005e1a2c81bc6dd6593ea.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/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.template.json new file mode 100644 index 0000000000000..324bf05c33e5e --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/ProducerStack.template.json @@ -0,0 +1,56 @@ +{ + "Resources": { + "MyBucketF68F3FF0": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Outputs": { + "ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58": { + "Value": { + "Fn::GetAtt": [ + "MyBucketF68F3FF0", + "Arn" + ] + }, + "Export": { + "Name": "ProducerStack:ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58" + } + } + }, + "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/aws-s3/test/integ.bucket-sharing.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdk.out new file mode 100644 index 0000000000000..b72fef144f05c --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets.json new file mode 100644 index 0000000000000..6e4902779fea7 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.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/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/cdkintegbucketsharingDefaultTestDeployAssertD8250F42.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/aws-s3/test/integ.bucket-sharing.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/integ.json new file mode 100644 index 0000000000000..a62a9208c2058 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "30.1.0", + "testCases": { + "cdk-integ-bucket-sharing/DefaultTest": { + "stacks": [ + "ConsumerStack" + ], + "assertionStack": "cdk-integ-bucket-sharing/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegbucketsharingDefaultTestDeployAssertD8250F42" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/manifest.json new file mode 100644 index 0000000000000..fd4be2df984f7 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/manifest.json @@ -0,0 +1,177 @@ +{ + "version": "30.1.0", + "artifacts": { + "ProducerStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ProducerStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ProducerStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ProducerStack.template.json", + "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}/72d18a5cfa63befafc29d9feb111797e3e5a8d80dd2005e1a2c81bc6dd6593ea.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ProducerStack.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": [ + "ProducerStack.assets" + ], + "metadata": { + "/ProducerStack/MyBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyBucketF68F3FF0" + } + ], + "/ProducerStack/Exports/Output{\"Fn::GetAtt\":[\"MyBucketF68F3FF0\",\"Arn\"]}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58" + } + ], + "/ProducerStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ProducerStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ProducerStack" + }, + "ConsumerStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ConsumerStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ConsumerStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ConsumerStack.template.json", + "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}/8256310f1a5d004f222c2df04da2c9bcf7d0e1416fc0c2f07ab472f9eb7858e3.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ConsumerStack.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": [ + "ProducerStack", + "ConsumerStack.assets" + ], + "metadata": { + "/ConsumerStack/MyUser/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyUserDC45028B" + } + ], + "/ConsumerStack/MyUser/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyUserDefaultPolicy7B897426" + } + ], + "/ConsumerStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ConsumerStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ConsumerStack" + }, + "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegbucketsharingDefaultTestDeployAssertD8250F42": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.template.json", + "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": [ + "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.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": [ + "cdkintegbucketsharingDefaultTestDeployAssertD8250F42.assets" + ], + "metadata": { + "/cdk-integ-bucket-sharing/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-bucket-sharing/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-bucket-sharing/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/tree.json similarity index 64% rename from packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/tree.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/tree.json index a7ee9710bdd05..a2f4d17bfdd8e 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.0.9" - } - }, "ProducerStack": { "id": "ProducerStack", "path": "ProducerStack", @@ -53,7 +45,23 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.0.9" + "version": "10.1.252" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ProducerStack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ProducerStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, @@ -152,12 +160,90 @@ "fqn": "@aws-cdk/aws-iam.User", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "ConsumerStack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "ConsumerStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" } + }, + "cdk-integ-bucket-sharing": { + "id": "cdk-integ-bucket-sharing", + "path": "cdk-integ-bucket-sharing", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-bucket-sharing/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-bucket-sharing/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-bucket-sharing/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-bucket-sharing/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-bucket-sharing/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ProducerStack.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ProducerStack.template.json deleted file mode 100644 index 08eb66859f88a..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/ProducerStack.template.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "Resources": { - "MyBucketF68F3FF0": { - "Type": "AWS::S3::Bucket", - "UpdateReplacePolicy": "Delete", - "DeletionPolicy": "Delete" - } - }, - "Outputs": { - "ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58": { - "Value": { - "Fn::GetAtt": [ - "MyBucketF68F3FF0", - "Arn" - ] - }, - "Export": { - "Name": "ProducerStack:ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58" - } - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/cdk.out deleted file mode 100644 index 90bef2e09ad39..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/cdk.out +++ /dev/null @@ -1 +0,0 @@ -{"version":"17.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/integ.json deleted file mode 100644 index a514368e7d9fe..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/integ.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": "20.0.0", - "testCases": { - "integ.bucket-sharing.lit": { - "stacks": [ - "*" - ], - "diffAssets": false, - "stackUpdateWorkflow": true - } - }, - "synthContext": {}, - "enableLookups": false -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/manifest.json deleted file mode 100644 index 3abf44d21065b..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.js.snapshot/manifest.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "version": "17.0.0", - "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, - "ProducerStack": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "ProducerStack.template.json", - "validateOnSynth": false - }, - "metadata": { - "/ProducerStack/MyBucket/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MyBucketF68F3FF0" - } - ], - "/ProducerStack/Exports/Output{\"Fn::GetAtt\":[\"MyBucketF68F3FF0\",\"Arn\"]}": [ - { - "type": "aws:cdk:logicalId", - "data": "ExportsOutputFnGetAttMyBucketF68F3FF0Arn0F7E8E58" - } - ] - }, - "displayName": "ProducerStack" - }, - "ConsumerStack": { - "type": "aws:cloudformation:stack", - "environment": "aws://unknown-account/unknown-region", - "properties": { - "templateFile": "ConsumerStack.template.json", - "validateOnSynth": false - }, - "dependencies": [ - "ProducerStack" - ], - "metadata": { - "/ConsumerStack/MyUser/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MyUserDC45028B" - } - ], - "/ConsumerStack/MyUser/DefaultPolicy/Resource": [ - { - "type": "aws:cdk:logicalId", - "data": "MyUserDefaultPolicy7B897426" - } - ] - }, - "displayName": "ConsumerStack" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.ts similarity index 82% rename from packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.ts rename to packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.ts index e5108cd2389d5..efce9843d0359 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.lit.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket-sharing.ts @@ -1,12 +1,10 @@ -/// !cdk-integ * import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; const app = new cdk.App(); -/// !show - /** * Stack that defines the bucket */ @@ -40,7 +38,7 @@ class Consumer extends cdk.Stack { } const producer = new Producer(app, 'ProducerStack'); -new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket }); -/// !hide -app.synth(); +new IntegTest(app, 'cdk-integ-bucket-sharing', { + testCases: [new Consumer(app, 'ConsumerStack', { userBucket: producer.myBucket })], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-s3-urls.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-domain-name.assets.json similarity index 88% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-s3-urls.assets.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-domain-name.assets.json index c36f09e0ecc94..f6f1e081b00e4 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-s3-urls.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-domain-name.assets.json @@ -1,9 +1,9 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "3ef2de923dd866776ef065e9d3915359136b24280dbb0244c322a1badc1f3fff": { "source": { - "path": "aws-cdk-s3-urls.template.json", + "path": "aws-cdk-domain-name.template.json", "packaging": "file" }, "destinations": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-s3-urls.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-domain-name.template.json similarity index 100% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-s3-urls.template.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/aws-cdk-domain-name.template.json diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets.json new file mode 100644 index 0000000000000..c81c0689ba16a --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.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/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/cdkintegbucketdomainnameDefaultTestDeployAssert72465477.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/aws-s3/test/integ.bucket.domain-name.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/integ.json index 7cd8e272a81cb..351a9367bae02 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket.domain-name": { + "cdk-integ-bucket-domain-name/DefaultTest": { "stacks": [ - "aws-cdk-s3-urls" + "aws-cdk-domain-name" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-bucket-domain-name/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegbucketdomainnameDefaultTestDeployAssert72465477" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/manifest.json index 2b08e23195b76..5ba5c31306575 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/manifest.json @@ -1,25 +1,19 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, - "aws-cdk-s3-urls.assets": { + "aws-cdk-domain-name.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "aws-cdk-s3-urls.assets.json", + "file": "aws-cdk-domain-name.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "aws-cdk-s3-urls": { + "aws-cdk-domain-name": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "aws-cdk-s3-urls.template.json", + "templateFile": "aws-cdk-domain-name.template.json", "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}", @@ -27,7 +21,7 @@ "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "aws-cdk-s3-urls.assets" + "aws-cdk-domain-name.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -36,41 +30,94 @@ } }, "dependencies": [ - "aws-cdk-s3-urls.assets" + "aws-cdk-domain-name.assets" ], "metadata": { - "/aws-cdk-s3-urls/MyBucket/Resource": [ + "/aws-cdk-domain-name/MyBucket/Resource": [ { "type": "aws:cdk:logicalId", "data": "MyBucketF68F3FF0" } ], - "/aws-cdk-s3-urls/RealBucketDomain": [ + "/aws-cdk-domain-name/RealBucketDomain": [ { "type": "aws:cdk:logicalId", "data": "RealBucketDomain" } ], - "/aws-cdk-s3-urls/ImportedBucketDomain": [ + "/aws-cdk-domain-name/ImportedBucketDomain": [ { "type": "aws:cdk:logicalId", "data": "ImportedBucketDomain" } ], - "/aws-cdk-s3-urls/BootstrapVersion": [ + "/aws-cdk-domain-name/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/aws-cdk-s3-urls/CheckBootstrapVersion": [ + "/aws-cdk-domain-name/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "aws-cdk-s3-urls" + "displayName": "aws-cdk-domain-name" + }, + "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegbucketdomainnameDefaultTestDeployAssert72465477": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.template.json", + "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": [ + "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.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": [ + "cdkintegbucketdomainnameDefaultTestDeployAssert72465477.assets" + ], + "metadata": { + "/cdk-integ-bucket-domain-name/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-bucket-domain-name/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-bucket-domain-name/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/tree.json index 95617a948d928..15a1d70df873c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.js.snapshot/tree.json @@ -4,25 +4,17 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "aws-cdk-s3-urls": { - "id": "aws-cdk-s3-urls", - "path": "aws-cdk-s3-urls", + "aws-cdk-domain-name": { + "id": "aws-cdk-domain-name", + "path": "aws-cdk-domain-name", "children": { "MyBucket": { "id": "MyBucket", - "path": "aws-cdk-s3-urls/MyBucket", + "path": "aws-cdk-domain-name/MyBucket", "children": { "Resource": { "id": "Resource", - "path": "aws-cdk-s3-urls/MyBucket/Resource", + "path": "aws-cdk-domain-name/MyBucket/Resource", "attributes": { "aws:cdk:cloudformation:type": "AWS::S3::Bucket", "aws:cdk:cloudformation:props": {} @@ -40,7 +32,7 @@ }, "MyBucket2": { "id": "MyBucket2", - "path": "aws-cdk-s3-urls/MyBucket2", + "path": "aws-cdk-domain-name/MyBucket2", "constructInfo": { "fqn": "@aws-cdk/aws-s3.BucketBase", "version": "0.0.0" @@ -48,30 +40,108 @@ }, "RealBucketDomain": { "id": "RealBucketDomain", - "path": "aws-cdk-s3-urls/RealBucketDomain", + "path": "aws-cdk-domain-name/RealBucketDomain", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" } }, "ImportedBucketDomain": { "id": "ImportedBucketDomain", - "path": "aws-cdk-s3-urls/ImportedBucketDomain", + "path": "aws-cdk-domain-name/ImportedBucketDomain", "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-domain-name/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-domain-name/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-bucket-domain-name": { + "id": "cdk-integ-bucket-domain-name", + "path": "cdk-integ-bucket-domain-name", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-bucket-domain-name/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-bucket-domain-name/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-bucket-domain-name/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-bucket-domain-name/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-bucket-domain-name/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts index 86619ff4d3e17..2be6add4c317b 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.domain-name.ts @@ -1,11 +1,11 @@ import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; class TestStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { super(scope, id); - /// !show const bucket = new s3.Bucket(this, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); @@ -15,10 +15,11 @@ class TestStack extends cdk.Stack { new cdk.CfnOutput(this, 'RealBucketDomain', { value: bucket.bucketDomainName }); new cdk.CfnOutput(this, 'ImportedBucketDomain', { value: bucket2.bucketDomainName }); - /// !hide } } const app = new cdk.App(); -new TestStack(app, 'aws-cdk-s3-urls'); -app.synth(); + +new IntegTest(app, 'cdk-integ-bucket-domain-name', { + testCases: [new TestStack(app, 'aws-cdk-domain-name')], +}); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/aws-cdk-s3.assets.json index 5a4df0849d791..b1a0dfd3a2622 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "6ae3d2477de11ae9c62bfb4d56e5a92e2357fb0d390af77b733130578aee7339": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets.json new file mode 100644 index 0000000000000..0fbecffa142a0 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegs3bucketDefaultTestDeployAssertB89636B8.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/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/cdkintegs3bucketDefaultTestDeployAssertB89636B8.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/aws-s3/test/integ.bucket.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/integ.json index e5cbca8a87998..4f0015ef4deff 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket": { + "cdk-integ-s3-bucket/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-s3-bucket/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegs3bucketDefaultTestDeployAssertB89636B8" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/manifest.json index cf5f45b7c3082..02f5db42af79b 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -83,6 +77,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegs3bucketDefaultTestDeployAssertB89636B8": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegs3bucketDefaultTestDeployAssertB89636B8.template.json", + "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": [ + "cdkintegs3bucketDefaultTestDeployAssertB89636B8.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": [ + "cdkintegs3bucketDefaultTestDeployAssertB89636B8.assets" + ], + "metadata": { + "/cdk-integ-s3-bucket/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-s3-bucket/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-s3-bucket/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/tree.json index cfad941f839d2..b8869297cae25 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -276,17 +268,95 @@ "fqn": "@aws-cdk/aws-iam.User", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-s3-bucket": { + "id": "cdk-integ-s3-bucket", + "path": "cdk-integ-s3-bucket", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-s3-bucket/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-s3-bucket/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-s3-bucket/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-s3-bucket/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-s3-bucket/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/NotificationTestDefaultTestDeployAssertBFB81666.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/NotificationTestDefaultTestDeployAssertBFB81666.assets.json index eee5ef607d9db..65ace0540faa1 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/NotificationTestDefaultTestDeployAssertBFB81666.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/NotificationTestDefaultTestDeployAssertBFB81666.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/aws-cdk-s3-notifications.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/aws-cdk-s3-notifications.assets.json index 9db394e3de998..7c465ce50f598 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/aws-cdk-s3-notifications.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/aws-cdk-s3-notifications.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "0950e270b55171f331f16b0a63f107106782d89c7816c2ec3ba14a69c11be52d": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/cdk.out index 145739f539580..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"22.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/integ.json index 786c78b96c982..4a2cb2cd16b15 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "testCases": { "NotificationTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/manifest.json index 9068079d380c6..dd0024801e596 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-s3-notifications.assets": { "type": "cdk:asset-manifest", diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/tree.json index 2f81d672269cf..c0e23242f761c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.js.snapshot/tree.json @@ -39,7 +39,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.252" } } }, @@ -159,7 +159,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.252" } }, "BootstrapVersion": { @@ -197,7 +197,7 @@ "path": "NotificationTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.252" } }, "DeployAssert": { @@ -243,7 +243,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.168" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.ts index 59092658fb929..c8a16e067d8a6 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.notifications.ts @@ -15,5 +15,3 @@ new s3.Bucket(stack, 'MyEventBridgeBucket', { new integ.IntegTest(app, 'NotificationTest', { testCases: [stack], }); - -app.synth(); diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/aws-cdk-s3-access-logs.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/aws-cdk-s3-access-logs.assets.json index 1b4fa26e8804e..9c6efb372abf0 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/aws-cdk-s3-access-logs.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/aws-cdk-s3-access-logs.assets.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "files": { "f58a2b25314952a1a5a6b42c6b9092caf2710430af09ba4f5d807e60f2fd3542": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdk.out index 145739f539580..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"22.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets.json new file mode 100644 index 0000000000000..44d48a4bd52ea --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.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/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/cdkintegs3accesslogsDefaultTestDeployAssert37A16466.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/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/integ.json index eba84b97fa6de..db07e940c872b 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "22.0.0", + "version": "30.1.0", "testCases": { - "integ.bucket.server-access-logs": { + "cdk-integ-s3-access-logs/DefaultTest": { "stacks": [ "aws-cdk-s3-access-logs" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-s3-access-logs/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegs3accesslogsDefaultTestDeployAssert37A16466" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/manifest.json index 2a1a113d65e6d..f8bde1cb1a252 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "22.0.0", + "version": "30.1.0", "artifacts": { "aws-cdk-s3-access-logs.assets": { "type": "cdk:asset-manifest", @@ -66,6 +66,53 @@ }, "displayName": "aws-cdk-s3-access-logs" }, + "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegs3accesslogsDefaultTestDeployAssert37A16466": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.template.json", + "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": [ + "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.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": [ + "cdkintegs3accesslogsDefaultTestDeployAssert37A16466.assets" + ], + "metadata": { + "/cdk-integ-s3-access-logs/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-s3-access-logs/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-s3-access-logs/DefaultTest/DeployAssert" + }, "Tree": { "type": "cdk:tree", "properties": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/tree.json index 2cdf059009410..dc67221905049 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.js.snapshot/tree.json @@ -148,12 +148,66 @@ "version": "0.0.0" } }, + "cdk-integ-s3-access-logs": { + "id": "cdk-integ-s3-access-logs", + "path": "cdk-integ-s3-access-logs", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-s3-access-logs/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-s3-access-logs/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-s3-access-logs/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-s3-access-logs/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-s3-access-logs/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, "Tree": { "id": "Tree", "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.189" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.ts index 3373257e5529c..ac9ca66688cc2 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.server-access-logs.ts @@ -1,5 +1,6 @@ #!/usr/bin/env node import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; const app = new cdk.App(); @@ -16,4 +17,6 @@ new s3.Bucket(stack, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); -app.synth(); +new IntegTest(app, 'cdk-integ-s3-access-logs', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.ts index 506c9c952a41b..ec8b536ea887e 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.ts @@ -1,6 +1,7 @@ #!/usr/bin/env node import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; const app = new cdk.App(); @@ -21,4 +22,6 @@ const user = new iam.User(stack, 'MyUser'); bucket.grantReadWrite(user); otherwiseEncryptedBucket.grantRead(user); -app.synth(); +new IntegTest(app, 'cdk-integ-s3-bucket', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/aws-cdk-s3-urls.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/aws-cdk-s3-urls.assets.json similarity index 96% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/aws-cdk-s3-urls.assets.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/aws-cdk-s3-urls.assets.json index a50f14c71b58a..c7c009a8b4f4c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/aws-cdk-s3-urls.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/aws-cdk-s3-urls.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "efcd9b5b8fd4dda412d0411dc133a79ecdb73e7451f792b4b4dc31ffe6814e4c": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/aws-cdk-s3-urls.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/aws-cdk-s3-urls.template.json similarity index 100% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/aws-cdk-s3-urls.template.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/aws-cdk-s3-urls.template.json diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdk.out new file mode 100644 index 0000000000000..b72fef144f05c --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets.json new file mode 100644 index 0000000000000..72ea9cdfd1dd3 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.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/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.template.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/cdkintegs3urlsDefaultTestDeployAssertDB43F13E.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/aws-s3/test/integ.bucket.url.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/integ.json new file mode 100644 index 0000000000000..19979740944e4 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "30.1.0", + "testCases": { + "cdk-integ-s3-urls/DefaultTest": { + "stacks": [ + "aws-cdk-s3-urls" + ], + "assertionStack": "cdk-integ-s3-urls/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegs3urlsDefaultTestDeployAssertDB43F13E" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/manifest.json similarity index 57% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/manifest.json rename to packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/manifest.json index 2c9b86e9335fd..66384b0d9c930 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3-urls.assets": { "type": "cdk:asset-manifest", "properties": { @@ -89,6 +83,59 @@ ] }, "displayName": "aws-cdk-s3-urls" + }, + "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegs3urlsDefaultTestDeployAssertDB43F13E": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.template.json", + "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": [ + "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.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": [ + "cdkintegs3urlsDefaultTestDeployAssertDB43F13E.assets" + ], + "metadata": { + "/cdk-integ-s3-urls/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-s3-urls/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-s3-urls/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/tree.json new file mode 100644 index 0000000000000..1461eabddf38b --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.js.snapshot/tree.json @@ -0,0 +1,163 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-s3-urls": { + "id": "aws-cdk-s3-urls", + "path": "aws-cdk-s3-urls", + "children": { + "MyBucket": { + "id": "MyBucket", + "path": "aws-cdk-s3-urls/MyBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-s3-urls/MyBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.CfnBucket", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.Bucket", + "version": "0.0.0" + } + }, + "BucketURL": { + "id": "BucketURL", + "path": "aws-cdk-s3-urls/BucketURL", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "ObjectURL": { + "id": "ObjectURL", + "path": "aws-cdk-s3-urls/ObjectURL", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "VirtualHostedObjectURL": { + "id": "VirtualHostedObjectURL", + "path": "aws-cdk-s3-urls/VirtualHostedObjectURL", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "VirtualHostedObjectURLNonRegional": { + "id": "VirtualHostedObjectURLNonRegional", + "path": "aws-cdk-s3-urls/VirtualHostedObjectURLNonRegional", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "S3ObjectURL": { + "id": "S3ObjectURL", + "path": "aws-cdk-s3-urls/S3ObjectURL", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3-urls/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3-urls/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-s3-urls": { + "id": "cdk-integ-s3-urls", + "path": "cdk-integ-s3-urls", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-s3-urls/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-s3-urls/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-s3-urls/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-s3-urls/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-s3-urls/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/cdk.out deleted file mode 100644 index 588d7b269d34f..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/cdk.out +++ /dev/null @@ -1 +0,0 @@ -{"version":"20.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/integ.json deleted file mode 100644 index ebc1d60d49eb9..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/integ.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "version": "20.0.0", - "testCases": { - "integ.bucket.url.lit": { - "stacks": [ - "aws-cdk-s3-urls" - ], - "diffAssets": false, - "stackUpdateWorkflow": true - } - }, - "synthContext": {}, - "enableLookups": false -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/tree.json deleted file mode 100644 index 5bcc462859559..0000000000000 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.js.snapshot/tree.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "aws-cdk-s3-urls": { - "id": "aws-cdk-s3-urls", - "path": "aws-cdk-s3-urls", - "children": { - "MyBucket": { - "id": "MyBucket", - "path": "aws-cdk-s3-urls/MyBucket", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-s3-urls/MyBucket/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::S3::Bucket", - "aws:cdk:cloudformation:props": {} - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-s3.CfnBucket", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-s3.Bucket", - "version": "0.0.0" - } - }, - "BucketURL": { - "id": "BucketURL", - "path": "aws-cdk-s3-urls/BucketURL", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "ObjectURL": { - "id": "ObjectURL", - "path": "aws-cdk-s3-urls/ObjectURL", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "VirtualHostedObjectURL": { - "id": "VirtualHostedObjectURL", - "path": "aws-cdk-s3-urls/VirtualHostedObjectURL", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "VirtualHostedObjectURLNonRegional": { - "id": "VirtualHostedObjectURLNonRegional", - "path": "aws-cdk-s3-urls/VirtualHostedObjectURLNonRegional", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, - "S3ObjectURL": { - "id": "S3ObjectURL", - "path": "aws-cdk-s3-urls/S3ObjectURL", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - } - }, - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.ts similarity index 85% rename from packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts rename to packages/@aws-cdk/aws-s3/test/integ.bucket.url.ts index e3655bf6e1f94..421df8bd28912 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.bucket.url.lit.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.bucket.url.ts @@ -1,11 +1,11 @@ import * as cdk from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import * as s3 from '../lib'; class TestStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { super(scope, id); - /// !show const bucket = new s3.Bucket(this, 'MyBucket', { removalPolicy: cdk.RemovalPolicy.DESTROY, }); @@ -15,10 +15,11 @@ class TestStack extends cdk.Stack { new cdk.CfnOutput(this, 'VirtualHostedObjectURL', { value: bucket.virtualHostedUrlForObject('myfolder/myfile.txt') }); new cdk.CfnOutput(this, 'VirtualHostedObjectURLNonRegional', { value: bucket.virtualHostedUrlForObject('myfolder/myfile.txt', { regional: false }) }); new cdk.CfnOutput(this, 'S3ObjectURL', { value: bucket.s3UrlForObject('myfolder/myfile.txt') }); - /// !hide } } const app = new cdk.App(); -new TestStack(app, 'aws-cdk-s3-urls'); -app.synth(); + +new IntegTest(app, 'cdk-integ-s3-urls', { + testCases: [new TestStack(app, 'aws-cdk-s3-urls')], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/aws-cdk-s3.assets.json index e73c5ea2885ca..8a75c282efdc2 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "21.0.0", + "version": "30.1.0", "files": { "928a24cbf7a16b7c4d15a9ceca38a2f7f016495b93db9bdf0160accc3d13876c": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdk.out index 8ecc185e9dbee..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"21.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets.json new file mode 100644 index 0000000000000..21188babbd388 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.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/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.template.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.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/aws-s3/test/integ.lifecycle-expiration.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/integ.json index 286d239e483cd..16308002dcfe8 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "21.0.0", + "version": "30.1.0", "testCases": { - "integ.lifecycle-expiration": { + "cdk-integ-lifecycle-expiration/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert", + "assertionStackName": "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/manifest.json index b7ae856f8f23f..0f24d4e0277a4 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "21.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -59,6 +53,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.template.json", + "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": [ + "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.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": [ + "cdkinteglifecycleexpirationDefaultTestDeployAssertDFC0D8F1.assets" + ], + "metadata": { + "/cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/tree.json index 62d43a017ab0e..64e9161bab062 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.140" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -49,12 +41,90 @@ "fqn": "@aws-cdk/aws-s3.Bucket", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, "constructInfo": { "fqn": "@aws-cdk/core.Stack", "version": "0.0.0" } + }, + "cdk-integ-lifecycle-expiration": { + "id": "cdk-integ-lifecycle-expiration", + "path": "cdk-integ-lifecycle-expiration", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-lifecycle-expiration/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-lifecycle-expiration/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-lifecycle-expiration/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.ts b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.ts index 211ac74c8261d..eaaab2e6f25db 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle-expiration.ts @@ -1,4 +1,5 @@ import { App, Duration, Stack } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import { Bucket } from '../lib'; const app = new App(); @@ -12,4 +13,6 @@ new Bucket(stack, 'MyBucket', { }], }); -app.synth(); \ No newline at end of file +new IntegTest(app, 'cdk-integ-lifecycle-expiration', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/aws-cdk-s3.assets.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/aws-cdk-s3.assets.json index d122bdeed0d38..d0a5cb96b7665 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/aws-cdk-s3.assets.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/aws-cdk-s3.assets.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "30.1.0", "files": { "ec43659201be5ffe7c1311b82c63224f177655acd30be0d6f1b0b377a9915825": { "source": { diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdk.out b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdk.out index 588d7b269d34f..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets.json new file mode 100644 index 0000000000000..dbb0b2c6c9725 --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets.json @@ -0,0 +1,19 @@ +{ + "version": "30.1.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.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/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.template.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/cdkinteglifecycleDefaultTestDeployAssert83FA03B1.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/aws-s3/test/integ.lifecycle.js.snapshot/integ.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/integ.json index 7ea8db89e32c8..913066fd7cda7 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/integ.json @@ -1,14 +1,12 @@ { - "version": "20.0.0", + "version": "30.1.0", "testCases": { - "integ.lifecycle": { + "cdk-integ-lifecycle/DefaultTest": { "stacks": [ "aws-cdk-s3" ], - "diffAssets": false, - "stackUpdateWorkflow": true + "assertionStack": "cdk-integ-lifecycle/DefaultTest/DeployAssert", + "assertionStackName": "cdkinteglifecycleDefaultTestDeployAssert83FA03B1" } - }, - "synthContext": {}, - "enableLookups": false + } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/manifest.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/manifest.json index 4cc58b12d361b..07b06677e1601 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "30.1.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-s3.assets": { "type": "cdk:asset-manifest", "properties": { @@ -59,6 +53,59 @@ ] }, "displayName": "aws-cdk-s3" + }, + "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkinteglifecycleDefaultTestDeployAssert83FA03B1": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.template.json", + "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": [ + "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.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": [ + "cdkinteglifecycleDefaultTestDeployAssert83FA03B1.assets" + ], + "metadata": { + "/cdk-integ-lifecycle/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-lifecycle/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-lifecycle/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/tree.json b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/tree.json index 0779286d122f6..9f6808d78e9b5 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-s3": { "id": "aws-cdk-s3", "path": "aws-cdk-s3", @@ -52,17 +44,95 @@ "fqn": "@aws-cdk/aws-s3.Bucket", "version": "0.0.0" } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-s3/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-s3/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-lifecycle": { + "id": "cdk-integ-lifecycle", + "path": "cdk-integ-lifecycle", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-lifecycle/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-lifecycle/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.252" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-lifecycle/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-lifecycle/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-lifecycle/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.252" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.ts b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.ts index 249480959e414..af506cbdd658e 100644 --- a/packages/@aws-cdk/aws-s3/test/integ.lifecycle.ts +++ b/packages/@aws-cdk/aws-s3/test/integ.lifecycle.ts @@ -1,4 +1,5 @@ import { App, RemovalPolicy, Stack } from '@aws-cdk/core'; +import { IntegTest } from '@aws-cdk/integ-tests'; import { Bucket } from '../lib'; const app = new App(); @@ -20,4 +21,6 @@ new Bucket(stack, 'MyBucket', { removalPolicy: RemovalPolicy.DESTROY, }); -app.synth(); +new IntegTest(app, 'cdk-integ-lifecycle', { + testCases: [stack], +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index bc49b5b6198ee..de80530b9ab6a 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -835,22 +835,38 @@ export class SecretTargetAttachment extends SecretBase implements ISecretTargetA protected readonly autoCreatePolicy = true; + private readonly attachedSecret: ISecret; + constructor(scope: Construct, id: string, props: SecretTargetAttachmentProps) { super(scope, id); + this.attachedSecret = props.secret; const attachment = new secretsmanager.CfnSecretTargetAttachment(this, 'Resource', { - secretId: props.secret.secretArn, + secretId: this.attachedSecret.secretArn, targetId: props.target.asSecretAttachmentTarget().targetId, targetType: attachmentTargetTypeToString(props.target.asSecretAttachmentTarget().targetType), }); - this.encryptionKey = props.secret.encryptionKey; - this.secretName = props.secret.secretName; + this.encryptionKey = this.attachedSecret.encryptionKey; + this.secretName = this.attachedSecret.secretName; // This allows to reference the secret after attachment (dependency). this.secretArn = attachment.ref; this.secretTargetAttachmentSecretArn = attachment.ref; } + + /** + * Forward any additions to the resource policy to the original secret. + * This is required because a secret can only have a single resource policy. + * If we do not forward policy additions, a new policy resource is created using the secret attachment ARN. + * This ends up being rejected by CloudFormation. + */ + public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult { + if (FeatureFlags.of(this).isEnabled(cxapi.SECRETS_MANAGER_TARGET_ATTACHMENT_RESOURCE_POLICY)) { + return this.attachedSecret.addToResourcePolicy(statement); + } + return super.addToResourcePolicy(statement); + } } /** diff --git a/packages/@aws-cdk/aws-secretsmanager/test/policy.test.ts b/packages/@aws-cdk/aws-secretsmanager/test/policy.test.ts new file mode 100644 index 0000000000000..a40c409b007b5 --- /dev/null +++ b/packages/@aws-cdk/aws-secretsmanager/test/policy.test.ts @@ -0,0 +1,43 @@ +import { Template } from '@aws-cdk/assertions'; +import * as iam from '@aws-cdk/aws-iam'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as secretsmanager from '../lib'; +import { AttachmentTargetType, ISecretAttachmentTarget } from '../lib'; + +class MockAttachmentTarget extends cdk.Resource implements ISecretAttachmentTarget { + asSecretAttachmentTarget(): secretsmanager.SecretAttachmentTargetProps { + return { + targetId: 'mock-id', + targetType: AttachmentTargetType.RDS_DB_INSTANCE, + }; + } +} + +describe.each([ + [false, 2], + [true, 1], +])('@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments=%s', (featureFlagValue, expectedResourcePolicyCount) => { + const app = new cdk.App({ + context: { + [cxapi.SECRETS_MANAGER_TARGET_ATTACHMENT_RESOURCE_POLICY]: featureFlagValue, + }, + }); + const stack = new cdk.Stack(app); + + test('using addToResourcePolicy on a Secret and on a SecretAttachmentTarget attaching this Secret', () => { + // GIVEN + + const secret = new secretsmanager.Secret(stack, 'Secret'); + const servicePrincipalOne = new iam.ServicePrincipal('some-service-a'); + const servicePrincipalTwo = new iam.ServicePrincipal('some-service-b'); + const secretAttachment = secret.attach(new MockAttachmentTarget(stack, 'mock-target')); + + // WHEN + secret.grantRead(servicePrincipalOne); + secretAttachment.grantRead(servicePrincipalTwo); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::SecretsManager::ResourcePolicy', expectedResourcePolicyCount); + }); +}); diff --git a/packages/@aws-cdk/aws-ses/package.json b/packages/@aws-cdk/aws-ses/package.json index 3032c97aff112..01bfcb1c416f4 100644 --- a/packages/@aws-cdk/aws-ses/package.json +++ b/packages/@aws-cdk/aws-ses/package.json @@ -86,7 +86,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/jest": "^27.5.2", "jest": "^27.5.1" }, diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/email.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/email.ts index f75fa067bbf2c..81c71c4d13154 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/email.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/email.ts @@ -32,6 +32,7 @@ export class EmailSubscription implements sns.ITopicSubscription { endpoint: this.emailAddress, protocol: this.props.json ? sns.SubscriptionProtocol.EMAIL_JSON : sns.SubscriptionProtocol.EMAIL, filterPolicy: this.props.filterPolicy, + filterPolicyWithMessageBody: this.props.filterPolicyWithMessageBody, deadLetterQueue: this.props.deadLetterQueue, }; } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/lambda.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/lambda.ts index 7b5446abbdf23..a4b0cde12704c 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/lambda.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/lambda.ts @@ -45,6 +45,7 @@ export class LambdaSubscription implements sns.ITopicSubscription { endpoint: this.fn.functionArn, protocol: sns.SubscriptionProtocol.LAMBDA, filterPolicy: this.props.filterPolicy, + filterPolicyWithMessageBody: this.props.filterPolicyWithMessageBody, region: this.regionFromArn(topic), deadLetterQueue: this.props.deadLetterQueue, }; diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/sms.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/sms.ts index 151fc7b494a25..0f2446278def3 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/sms.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/sms.ts @@ -20,6 +20,7 @@ export class SmsSubscription implements sns.ITopicSubscription { endpoint: this.phoneNumber, protocol: sns.SubscriptionProtocol.SMS, filterPolicy: this.props.filterPolicy, + filterPolicyWithMessageBody: this.props.filterPolicyWithMessageBody, }; } } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts index ce55f1778265a..340643632876c 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/sqs.ts @@ -75,6 +75,7 @@ export class SqsSubscription implements sns.ITopicSubscription { protocol: sns.SubscriptionProtocol.SQS, rawMessageDelivery: this.props.rawMessageDelivery, filterPolicy: this.props.filterPolicy, + filterPolicyWithMessageBody: this.props.filterPolicyWithMessageBody, region: this.regionFromArn(topic), deadLetterQueue: this.props.deadLetterQueue, subscriptionDependency: queuePolicyDependable, diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/subscription.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/subscription.ts index b95d2b54bcc2e..291699ca304f1 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/subscription.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/subscription.ts @@ -11,7 +11,13 @@ export interface SubscriptionProps { * @default - all messages are delivered */ readonly filterPolicy?: { [attribute: string]: sns.SubscriptionFilter }; - + /** + * The filter policy that is applied on the message body. + * To apply a filter policy to the message attributes, use `filterPolicy`. A maximum of one of `filterPolicyWithMessageBody` and `filterPolicy` may be used. + * + * @default - all messages are delivered + */ + readonly filterPolicyWithMessageBody?: { [attribute: string]: sns.FilterOrPolicy }; /** * Queue to be used as dead letter queue. * If not passed no dead letter queue is enabled. diff --git a/packages/@aws-cdk/aws-sns-subscriptions/lib/url.ts b/packages/@aws-cdk/aws-sns-subscriptions/lib/url.ts index 1c3ddccf51520..bab121ba61a22 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/lib/url.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/lib/url.ts @@ -61,6 +61,7 @@ export class UrlSubscription implements sns.ITopicSubscription { protocol: this.protocol, rawMessageDelivery: this.props.rawMessageDelivery, filterPolicy: this.props.filterPolicy, + filterPolicyWithMessageBody: this.props.filterPolicyWithMessageBody, deadLetterQueue: this.props.deadLetterQueue, }; } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/package.json b/packages/@aws-cdk/aws-sns-subscriptions/package.json index 5c8d4c76df917..9bc3d86788313 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/package.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/package.json @@ -75,6 +75,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.assets.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.assets.json index 555987868e39f..1e8da21ab7952 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.assets.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.assets.json @@ -1,7 +1,7 @@ { - "version": "20.0.0", + "version": "22.0.0", "files": { - "451c86b70ff9eaa09b0558745f5aa97d2af847bd82e8960d44d5c91c88fa855a": { + "b4d5d97a3217325cd1f06b3e725bdfbb9c4fd3c5c4a6adba15b286efa9146e23": { "source": { "path": "aws-cdk-sns-lambda.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "451c86b70ff9eaa09b0558745f5aa97d2af847bd82e8960d44d5c91c88fa855a.json", + "objectKey": "b4d5d97a3217325cd1f06b3e725bdfbb9c4fd3c5c4a6adba15b286efa9146e23.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.template.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.template.json index 2bddd7e2aa658..9f3e5c86b34db 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.template.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/aws-cdk-sns-lambda.template.json @@ -241,6 +241,101 @@ ] } } + }, + "FilteredMessageBodyServiceRoleB2EB82B3": { + "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" + ] + ] + } + ] + } + }, + "FilteredMessageBody222AE8F1": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = function handler(event, _context, callback) {\n /* eslint-disable no-console */\n console.log('====================================================');\n console.log(JSON.stringify(event, undefined, 2));\n console.log('====================================================');\n return callback(undefined, event);\n}" + }, + "Role": { + "Fn::GetAtt": [ + "FilteredMessageBodyServiceRoleB2EB82B3", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "FilteredMessageBodyServiceRoleB2EB82B3" + ] + }, + "FilteredMessageBodyAllowInvokeawscdksnslambdaMyTopic6C62AB90FB54CEA4": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "FilteredMessageBody222AE8F1", + "Arn" + ] + }, + "Principal": "sns.amazonaws.com", + "SourceArn": { + "Ref": "MyTopic86869434" + } + } + }, + "FilteredMessageBodyMyTopicAD1F55C4": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Protocol": "lambda", + "TopicArn": { + "Ref": "MyTopic86869434" + }, + "Endpoint": { + "Fn::GetAtt": [ + "FilteredMessageBody222AE8F1", + "Arn" + ] + }, + "FilterPolicy": { + "background": { + "color": [ + "red", + { + "prefix": "bl" + }, + { + "prefix": "ye" + } + ] + } + }, + "FilterPolicyScope": "MessageBody" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/cdk.out b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/cdk.out index 588d7b269d34f..145739f539580 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"20.0.0"} \ No newline at end of file +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/integ.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/integ.json index 252910a4df52c..3f4ce5ecc9748 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "20.0.0", + "version": "22.0.0", "testCases": { "integ.sns-lambda": { "stacks": [ diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/manifest.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/manifest.json index f4d3c8f7b4c69..a1dc0e7aeeecc 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/manifest.json @@ -1,12 +1,6 @@ { - "version": "20.0.0", + "version": "22.0.0", "artifacts": { - "Tree": { - "type": "cdk:tree", - "properties": { - "file": "tree.json" - } - }, "aws-cdk-sns-lambda.assets": { "type": "cdk:asset-manifest", "properties": { @@ -23,7 +17,7 @@ "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}/451c86b70ff9eaa09b0558745f5aa97d2af847bd82e8960d44d5c91c88fa855a.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b4d5d97a3217325cd1f06b3e725bdfbb9c4fd3c5c4a6adba15b286efa9146e23.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -105,6 +99,30 @@ "data": "FilteredMyTopicC8395C27" } ], + "/aws-cdk-sns-lambda/FilteredMessageBody/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FilteredMessageBodyServiceRoleB2EB82B3" + } + ], + "/aws-cdk-sns-lambda/FilteredMessageBody/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FilteredMessageBody222AE8F1" + } + ], + "/aws-cdk-sns-lambda/FilteredMessageBody/AllowInvoke:awscdksnslambdaMyTopic6C62AB90": [ + { + "type": "aws:cdk:logicalId", + "data": "FilteredMessageBodyAllowInvokeawscdksnslambdaMyTopic6C62AB90FB54CEA4" + } + ], + "/aws-cdk-sns-lambda/FilteredMessageBody/MyTopic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FilteredMessageBodyMyTopicAD1F55C4" + } + ], "/aws-cdk-sns-lambda/BootstrapVersion": [ { "type": "aws:cdk:logicalId", @@ -119,6 +137,12 @@ ] }, "displayName": "aws-cdk-sns-lambda" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/tree.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/tree.json index ca55020a7b40f..58272873148d2 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.js.snapshot/tree.json @@ -4,14 +4,6 @@ "id": "App", "path": "", "children": { - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" - } - }, "aws-cdk-sns-lambda": { "id": "aws-cdk-sns-lambda", "path": "aws-cdk-sns-lambda", @@ -46,6 +38,14 @@ "id": "ServiceRole", "path": "aws-cdk-sns-lambda/Echo/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-sns-lambda/Echo/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-sns-lambda/Echo/ServiceRole/Resource", @@ -269,6 +269,14 @@ "id": "ServiceRole", "path": "aws-cdk-sns-lambda/Filtered/ServiceRole", "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-sns-lambda/Filtered/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, "Resource": { "id": "Resource", "path": "aws-cdk-sns-lambda/Filtered/ServiceRole/Resource", @@ -429,17 +437,203 @@ "fqn": "@aws-cdk/aws-lambda.Function", "version": "0.0.0" } + }, + "FilteredMessageBody": { + "id": "FilteredMessageBody", + "path": "aws-cdk-sns-lambda/FilteredMessageBody", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "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" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = function handler(event, _context, callback) {\n /* eslint-disable no-console */\n console.log('====================================================');\n console.log(JSON.stringify(event, undefined, 2));\n console.log('====================================================');\n return callback(undefined, event);\n}" + }, + "role": { + "Fn::GetAtt": [ + "FilteredMessageBodyServiceRoleB2EB82B3", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "AllowInvoke:awscdksnslambdaMyTopic6C62AB90": { + "id": "AllowInvoke:awscdksnslambdaMyTopic6C62AB90", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/AllowInvoke:awscdksnslambdaMyTopic6C62AB90", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "FilteredMessageBody222AE8F1", + "Arn" + ] + }, + "principal": "sns.amazonaws.com", + "sourceArn": { + "Ref": "MyTopic86869434" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnPermission", + "version": "0.0.0" + } + }, + "MyTopic": { + "id": "MyTopic", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/MyTopic", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-sns-lambda/FilteredMessageBody/MyTopic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", + "aws:cdk:cloudformation:props": { + "protocol": "lambda", + "topicArn": { + "Ref": "MyTopic86869434" + }, + "endpoint": { + "Fn::GetAtt": [ + "FilteredMessageBody222AE8F1", + "Arn" + ] + }, + "filterPolicy": { + "background": { + "color": [ + "red", + { + "prefix": "bl" + }, + { + "prefix": "ye" + } + ] + } + }, + "filterPolicyScope": "MessageBody" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.CfnSubscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.Subscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-sns-lambda/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-sns-lambda/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } } }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.85" + "version": "10.1.189" } } }, "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.85" + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" } } } \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.ts b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.ts index bd847b73d18f0..da150e9929861 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-lambda.ts @@ -1,3 +1,5 @@ + + import * as lambda from '@aws-cdk/aws-lambda'; import * as sns from '@aws-cdk/aws-sns'; import * as sqs from '@aws-cdk/aws-sqs'; @@ -10,23 +12,23 @@ class SnsToLambda extends cdk.Stack { const topic = new sns.Topic(this, 'MyTopic'); - const fction = new lambda.Function(this, 'Echo', { + const func = new lambda.Function(this, 'Echo', { handler: 'index.handler', runtime: lambda.Runtime.NODEJS_14_X, code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), }); - topic.addSubscription(new subs.LambdaSubscription(fction, { + topic.addSubscription(new subs.LambdaSubscription(func, { deadLetterQueue: new sqs.Queue(this, 'DeadLetterQueue'), })); - const fctionFiltered = new lambda.Function(this, 'Filtered', { + const funcFiltered = new lambda.Function(this, 'Filtered', { handler: 'index.handler', runtime: lambda.Runtime.NODEJS_14_X, code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), }); - topic.addSubscription(new subs.LambdaSubscription(fctionFiltered, { + topic.addSubscription(new subs.LambdaSubscription(funcFiltered, { filterPolicy: { color: sns.SubscriptionFilter.stringFilter({ allowlist: ['red'], @@ -40,6 +42,23 @@ class SnsToLambda extends cdk.Stack { }), }, })); + + const funcFilteredWithMessageBody = new lambda.Function(this, 'FilteredMessageBody', { + handler: 'index.handler', + runtime: lambda.Runtime.NODEJS_14_X, + code: lambda.Code.fromInline(`exports.handler = ${handler.toString()}`), + }); + + topic.addSubscription(new subs.LambdaSubscription(funcFilteredWithMessageBody, { + filterPolicyWithMessageBody: { + background: sns.FilterOrPolicy.policy({ + color: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.stringFilter({ + allowlist: ['red'], + matchPrefixes: ['bl', 'ye'], + })), + }), + }, + })); } } diff --git a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.assets.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.assets.json similarity index 63% rename from packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.assets.json rename to packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.assets.json index e9c52dc148e48..5c5893e1b8478 100644 --- a/packages/@aws-cdk/aws-ec2/test/integ.launch-template.js.snapshot/TestStack.assets.json +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.assets.json @@ -1,15 +1,15 @@ { - "version": "21.0.0", + "version": "22.0.0", "files": { - "d17275411e4cfac0e49078863acdd9766783f143736b4534a3a0f1b5a4de118a": { + "706116cb7bbce00b1ab402aeeaa66b35fc2fef8e57e4192f8ee4747dc5864691": { "source": { - "path": "TestStack.template.json", + "path": "QueueStack.template.json", "packaging": "file" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "d17275411e4cfac0e49078863acdd9766783f143736b4534a3a0f1b5a4de118a.json", + "objectKey": "706116cb7bbce00b1ab402aeeaa66b35fc2fef8e57e4192f8ee4747dc5864691.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.template.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.template.json new file mode 100644 index 0000000000000..1b75dd29570ef --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/QueueStack.template.json @@ -0,0 +1,163 @@ +{ + "Resources": { + "MyQueueE6CA6235": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "MyQueuePolicy6BBEDDAC": { + "Type": "AWS::SQS::QueuePolicy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Fn::ImportValue": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "MyQueueE6CA6235", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "Queues": [ + { + "Ref": "MyQueueE6CA6235" + } + ] + } + }, + "MyQueueSnsToSqsStackMyTopic3F1182C25E300A0F": { + "Type": "AWS::SNS::Subscription", + "Properties": { + "Protocol": "sqs", + "TopicArn": { + "Fn::ImportValue": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + }, + "Endpoint": { + "Fn::GetAtt": [ + "MyQueueE6CA6235", + "Arn" + ] + }, + "FilterPolicy": { + "background": { + "color": [ + "red", + "green", + { + "anything-but": [ + "white", + "orange" + ] + } + ] + }, + "price": [ + { + "numeric": [ + "=", + 100 + ] + }, + { + "numeric": [ + "=", + 200 + ] + }, + { + "numeric": [ + ">", + 500 + ] + }, + { + "numeric": [ + "<", + 1000 + ] + }, + { + "numeric": [ + ">=", + 300, + "<=", + 350 + ] + }, + { + "numeric": [ + ">", + 2000, + "<", + 3000 + ] + } + ] + }, + "FilterPolicyScope": "MessageBody" + }, + "DependsOn": [ + "MyQueuePolicy6BBEDDAC" + ] + } + }, + "Outputs": { + "ExportsOutputRefMyQueueE6CA623512A57419": { + "Value": { + "Ref": "MyQueueE6CA6235" + }, + "Export": { + "Name": "QueueStack:ExportsOutputRefMyQueueE6CA623512A57419" + } + } + }, + "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/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets.json new file mode 100644 index 0000000000000..f35a1ebd0b58e --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets.json @@ -0,0 +1,32 @@ +{ + "version": "22.0.0", + "files": { + "278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4": { + "source": { + "path": "asset.278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.bundle", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "9c226b6b87c5f7d528d0a2cdc0627cfb3165de9fb9df32956d25a79356409185": { + "source": { + "path": "SNSSubscriptionsDefaultTestDeployAssertD77125EB.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9c226b6b87c5f7d528d0a2cdc0627cfb3165de9fb9df32956d25a79356409185.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/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.template.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.template.json new file mode 100644 index 0000000000000..857e8d4435869 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SNSSubscriptionsDefaultTestDeployAssertD77125EB.template.json @@ -0,0 +1,154 @@ +{ + "Resources": { + "AwsApiCallSNSpublish": { + "Type": "Custom::DeployAssert@SdkCallSNSpublish", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "SNS", + "api": "publish", + "parameters": { + "Message": "{ background: { color: 'green' }, price: 200 }", + "TopicArn": { + "Fn::ImportValue": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + } + }, + "flattenResponse": "false", + "salt": "1677122791193" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73": { + "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": [ + { + "Action": [ + "sns:Publish" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + }, + { + "Action": [ + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": [ + "*" + ] + } + ] + } + } + ] + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Runtime": "nodejs14.x", + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.zip" + }, + "Timeout": 120, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73", + "Arn" + ] + } + } + }, + "AwsApiCallSQSreceiveMessage": { + "Type": "Custom::DeployAssert@SdkCallSQSreceiveMessage", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F", + "Arn" + ] + }, + "service": "SQS", + "api": "receiveMessage", + "parameters": { + "QueueUrl": { + "Fn::ImportValue": "QueueStack:ExportsOutputRefMyQueueE6CA623512A57419" + }, + "WaitTimeSeconds": 20 + }, + "flattenResponse": "false", + "salt": "1677122791193" + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "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/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.assets.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.assets.json new file mode 100644 index 0000000000000..e01f9dadedc45 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "1b2f5417b0f02417ad80f41e818ff0917ea4b65ef69016cec3a20d314fe454bc": { + "source": { + "path": "SnsToSqsStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "1b2f5417b0f02417ad80f41e818ff0917ea4b65ef69016cec3a20d314fe454bc.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/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.template.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.template.json new file mode 100644 index 0000000000000..5406da3773d92 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/SnsToSqsStack.template.json @@ -0,0 +1,51 @@ +{ + "Resources": { + "MyTopic86869434": { + "Type": "AWS::SNS::Topic" + } + }, + "Outputs": { + "ExportsOutputRefMyTopic868694349D03D60F": { + "Value": { + "Ref": "MyTopic86869434" + }, + "Export": { + "Name": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + } + } + }, + "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/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.bundle/index.js b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/asset.278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.bundle/index.js similarity index 70% rename from packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.bundle/index.js rename to packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/asset.278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.bundle/index.js index d26d8b290deae..2bf09d6726a42 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/integ.bucket-deployment.js.snapshot/asset.e3900c1e0365029a742f5b51f9ccb158093a5e209a71840a41f9793498c3ed1b.bundle/index.js +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/asset.278d42fa865f60954d898636503d0ee86a6689d73dc50eb912fac62def0ef6a4.bundle/index.js @@ -1,3 +1,4 @@ +"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; @@ -39,29 +40,50 @@ var Matcher = class { }; var MatchResult = class { constructor(target) { - this.failures = []; + this.failuresHere = /* @__PURE__ */ new Map(); this.captures = /* @__PURE__ */ new Map(); this.finalized = false; + this.innerMatchFailures = /* @__PURE__ */ new Map(); + this._hasFailed = false; + this._failCount = 0; + this._cost = 0; this.target = target; } push(matcher, path, message) { return this.recordFailure({ matcher, path, message }); } recordFailure(failure) { - this.failures.push(failure); + const failKey = failure.path.join("."); + let list = this.failuresHere.get(failKey); + if (!list) { + list = []; + this.failuresHere.set(failKey, list); + } + this._failCount += 1; + this._cost += failure.cost ?? 1; + list.push(failure); + this._hasFailed = true; return this; } + get isSuccess() { + return !this._hasFailed; + } hasFailed() { - return this.failures.length !== 0; + return this._hasFailed; } get failCount() { - return this.failures.length; + return this._failCount; + } + get failCost() { + return this._cost; } compose(id, inner) { - const innerF = inner.failures; - this.failures.push(...innerF.map((f) => { - return { path: [id, ...f.path], message: f.message, matcher: f.matcher }; - })); + if (inner.hasFailed()) { + this._hasFailed = true; + this._failCount += inner.failCount; + this._cost += inner._cost; + this.innerMatchFailures.set(id, inner); + } inner.captures.forEach((vals, capture) => { vals.forEach((value) => this.recordCapture({ capture, value })); }); @@ -78,10 +100,154 @@ var MatchResult = class { return this; } toHumanStrings() { - return this.failures.map((r) => { - const loc = r.path.length === 0 ? "" : ` at ${r.path.join("")}`; + const failures = new Array(); + debugger; + recurse(this, []); + return failures.map((r) => { + const loc = r.path.length === 0 ? "" : ` at /${r.path.join("/")}`; return "" + r.message + loc + ` (using ${r.matcher.name} matcher)`; }); + function recurse(x, prefix) { + for (const fail of Array.from(x.failuresHere.values()).flat()) { + failures.push({ + matcher: fail.matcher, + message: fail.message, + path: [...prefix, ...fail.path] + }); + } + for (const [key, inner] of x.innerMatchFailures.entries()) { + recurse(inner, [...prefix, key]); + } + } + } + renderMismatch() { + if (!this.hasFailed()) { + return ""; + } + const parts = new Array(); + const indents = new Array(); + emitFailures(this, ""); + recurse(this); + return moveMarkersToFront(parts.join("").trimEnd()); + function emit(x) { + if (x === void 0) { + debugger; + } + parts.push(x.replace(/\n/g, ` +${indents.join("")}`)); + } + function emitFailures(r, path, scrapSet) { + for (const fail of r.failuresHere.get(path) ?? []) { + emit(`!! ${fail.message} +`); + } + scrapSet == null ? void 0 : scrapSet.delete(path); + } + function recurse(r) { + const remainingFailures = new Set(Array.from(r.failuresHere.keys()).filter((x) => x !== "")); + if (Array.isArray(r.target)) { + indents.push(" "); + emit("[\n"); + for (const [first, i] of enumFirst(range(r.target.length))) { + if (!first) { + emit(",\n"); + } + emitFailures(r, `${i}`, remainingFailures); + const innerMatcher = r.innerMatchFailures.get(`${i}`); + if (innerMatcher) { + emitFailures(innerMatcher, ""); + recurseComparingValues(innerMatcher, r.target[i]); + } else { + emit(renderAbridged(r.target[i])); + } + } + emitRemaining(); + indents.pop(); + emit("\n]"); + return; + } + if (r.target && typeof r.target === "object") { + indents.push(" "); + emit("{\n"); + const keys = Array.from(/* @__PURE__ */ new Set([ + ...Object.keys(r.target), + ...Array.from(remainingFailures) + ])).sort(); + for (const [first, key] of enumFirst(keys)) { + if (!first) { + emit(",\n"); + } + emitFailures(r, key, remainingFailures); + const innerMatcher = r.innerMatchFailures.get(key); + if (innerMatcher) { + emitFailures(innerMatcher, ""); + emit(`${jsonify(key)}: `); + recurseComparingValues(innerMatcher, r.target[key]); + } else { + emit(`${jsonify(key)}: `); + emit(renderAbridged(r.target[key])); + } + } + emitRemaining(); + indents.pop(); + emit("\n}"); + return; + } + emitRemaining(); + emit(jsonify(r.target)); + function emitRemaining() { + if (remainingFailures.size > 0) { + emit("\n"); + } + for (const key of remainingFailures) { + emitFailures(r, key); + } + } + } + function recurseComparingValues(inner, actualValue) { + if (inner.target === actualValue) { + return recurse(inner); + } + emit(renderAbridged(actualValue)); + emit(" <*> "); + recurse(inner); + } + function renderAbridged(x) { + if (Array.isArray(x)) { + switch (x.length) { + case 0: + return "[]"; + case 1: + return `[ ${renderAbridged(x[0])} ]`; + case 2: + if (x.every((e) => ["number", "boolean", "string"].includes(typeof e))) { + return `[ ${x.map(renderAbridged).join(", ")} ]`; + } + return "[ ... ]"; + default: + return "[ ... ]"; + } + } + if (x && typeof x === "object") { + const keys = Object.keys(x); + switch (keys.length) { + case 0: + return "{}"; + case 1: + return `{ ${JSON.stringify(keys[0])}: ${renderAbridged(x[keys[0]])} }`; + default: + return "{ ... }"; + } + } + return jsonify(x); + } + function jsonify(x) { + return JSON.stringify(x) ?? "undefined"; + } + function moveMarkersToFront(x) { + const re = /^(\s+)!!/gm; + return x.replace(re, (_, spaces) => `!!${spaces.substring(0, spaces.length - 2)}`); + } } recordCapture(options) { let values = this.captures.get(options.capture); @@ -92,6 +258,18 @@ var MatchResult = class { this.captures.set(options.capture, values); } }; +function* range(n) { + for (let i = 0; i < n; i++) { + yield i; + } +} +function* enumFirst(xs) { + let first = true; + for (const x of xs) { + yield [first, x]; + first = false; + } +} // ../assertions/lib/private/matchers/absent.ts var AbsentMatch = class extends Matcher { @@ -112,6 +290,51 @@ var AbsentMatch = class extends Matcher { } }; +// ../assertions/lib/private/sorting.ts +function sortKeyComparator(keyFn) { + return (a, b) => { + const ak = keyFn(a); + const bk = keyFn(b); + for (let i = 0; i < ak.length && i < bk.length; i++) { + const av = ak[i]; + const bv = bk[i]; + let diff = 0; + if (typeof av === "number" && typeof bv === "number") { + diff = av - bv; + } else if (typeof av === "string" && typeof bv === "string") { + diff = av.localeCompare(bv); + } + if (diff !== 0) { + return diff; + } + } + return bk.length - ak.length; + }; +} + +// ../assertions/lib/private/sparse-matrix.ts +var SparseMatrix = class { + constructor() { + this.matrix = /* @__PURE__ */ new Map(); + } + get(row, col) { + var _a; + return (_a = this.matrix.get(row)) == null ? void 0 : _a.get(col); + } + row(row) { + var _a; + return Array.from(((_a = this.matrix.get(row)) == null ? void 0 : _a.entries()) ?? []); + } + set(row, col, value) { + let r = this.matrix.get(row); + if (!r) { + r = /* @__PURE__ */ new Map(); + this.matrix.set(row, r); + } + r.set(col, value); + } +}; + // ../assertions/lib/private/type.ts function getType(obj) { return Array.isArray(obj) ? "array" : typeof obj; @@ -202,40 +425,85 @@ var ArrayMatch = class extends Matcher { message: `Expected type array but received ${getType(actual)}` }); } - if (!this.subsequence && this.pattern.length !== actual.length) { - return new MatchResult(actual).recordFailure({ + return this.subsequence ? this.testSubsequence(actual) : this.testFullArray(actual); + } + testFullArray(actual) { + const result = new MatchResult(actual); + let i = 0; + for (; i < this.pattern.length && i < actual.length; i++) { + const patternElement = this.pattern[i]; + const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); + const innerResult = matcher.test(actual[i]); + result.compose(`${i}`, innerResult); + } + if (i < this.pattern.length) { + result.recordFailure({ matcher: this, - path: [], - message: `Expected array of length ${this.pattern.length} but received ${actual.length}` + message: `Not enough elements in array (expecting ${this.pattern.length}, got ${actual.length})`, + path: [`${i}`] + }); + } + if (i < actual.length) { + result.recordFailure({ + matcher: this, + message: `Too many elements in array (expecting ${this.pattern.length}, got ${actual.length})`, + path: [`${i}`] }); } + return result; + } + testSubsequence(actual) { + const result = new MatchResult(actual); let patternIdx = 0; let actualIdx = 0; - const result = new MatchResult(actual); + const matches = new SparseMatrix(); while (patternIdx < this.pattern.length && actualIdx < actual.length) { const patternElement = this.pattern[patternIdx]; const matcher = Matcher.isMatcher(patternElement) ? patternElement : new LiteralMatch(this.name, patternElement, { partialObjects: this.partialObjects }); const matcherName = matcher.name; - if (this.subsequence && (matcherName == "absent" || matcherName == "anyValue")) { + if (matcherName == "absent" || matcherName == "anyValue") { throw new Error(`The Matcher ${matcherName}() cannot be nested within arrayWith()`); } const innerResult = matcher.test(actual[actualIdx]); - if (!this.subsequence || !innerResult.hasFailed()) { - result.compose(`[${actualIdx}]`, innerResult); + matches.set(patternIdx, actualIdx, innerResult); + actualIdx++; + if (innerResult.isSuccess) { + result.compose(`${actualIdx}`, innerResult); patternIdx++; - actualIdx++; - } else { - actualIdx++; } } - for (; patternIdx < this.pattern.length; patternIdx++) { - const pattern = this.pattern[patternIdx]; - const element = Matcher.isMatcher(pattern) || typeof pattern === "object" ? " " : ` [${pattern}] `; - result.recordFailure({ - matcher: this, - path: [], - message: `Missing element${element}at pattern index ${patternIdx}` - }); + if (patternIdx < this.pattern.length) { + for (let spi = 0; spi < patternIdx; spi++) { + const foundMatch = matches.row(spi).find(([, r]) => r.isSuccess); + if (!foundMatch) { + continue; + } + const [index] = foundMatch; + result.compose(`${index}`, new MatchResult(actual[index]).recordFailure({ + matcher: this, + message: `arrayWith pattern ${spi} matched here`, + path: [], + cost: 0 + })); + } + const failedMatches = matches.row(patternIdx); + failedMatches.sort(sortKeyComparator(([i, r]) => [r.failCost, i])); + if (failedMatches.length > 0) { + const [index, innerResult] = failedMatches[0]; + result.recordFailure({ + matcher: this, + message: `Could not match arrayWith pattern ${patternIdx}. This is the closest match`, + path: [`${index}`], + cost: 0 + }); + result.compose(`${index}`, innerResult); + } else { + result.recordFailure({ + matcher: this, + message: `Could not match arrayWith pattern ${patternIdx}. No more elements to try`, + path: [`${actual.length}`] + }); + } } return result; } @@ -261,8 +529,8 @@ var ObjectMatch = class extends Matcher { if (!(a in this.pattern)) { result.recordFailure({ matcher: this, - path: [`/${a}`], - message: "Unexpected key" + path: [a], + message: `Unexpected key ${a}` }); } } @@ -271,14 +539,14 @@ var ObjectMatch = class extends Matcher { if (!(patternKey in actual) && !(patternVal instanceof AbsentMatch)) { result.recordFailure({ matcher: this, - path: [`/${patternKey}`], - message: `Missing key '${patternKey}' among {${Object.keys(actual).join(",")}}` + path: [patternKey], + message: `Missing key '${patternKey}'` }); continue; } const matcher = Matcher.isMatcher(patternVal) ? patternVal : new LiteralMatch(this.name, patternVal, { partialObjects: this.partial }); const inner = matcher.test(actual[patternKey]); - result.compose(`/${patternKey}`, inner); + result.compose(patternKey, inner); } return result; } @@ -290,34 +558,37 @@ var SerializedJson = class extends Matcher { this.pattern = pattern; } test(actual) { - const result = new MatchResult(actual); if (getType(actual) !== "string") { - result.recordFailure({ + return new MatchResult(actual).recordFailure({ matcher: this, path: [], message: `Expected JSON as a string but found ${getType(actual)}` }); - return result; } let parsed; try { parsed = JSON.parse(actual); } catch (err) { if (err instanceof SyntaxError) { - result.recordFailure({ + return new MatchResult(actual).recordFailure({ matcher: this, path: [], message: `Invalid JSON string: ${actual}` }); - return result; } else { throw err; } } const matcher = Matcher.isMatcher(this.pattern) ? this.pattern : new LiteralMatch(this.name, this.pattern); const innerResult = matcher.test(parsed); - result.compose(`(${this.name})`, innerResult); - return result; + if (innerResult.hasFailed()) { + innerResult.recordFailure({ + matcher: this, + path: [], + message: "Encoded JSON value does not match" + }); + } + return innerResult; } }; var NotMatch = class extends Matcher { @@ -506,10 +777,7 @@ var AssertionHandler = class extends CustomResourceHandler { failed: true, assertion: JSON.stringify({ status: "fail", - message: [ - ...matchResult.toHumanStrings(), - JSON.stringify(matchResult.target, void 0, 2) - ].join("\n") + message: matchResult.renderMismatch() }) }; if (request2.failDeployment) { @@ -542,6 +810,8 @@ var MatchCreator = class { return Match.objectLike(v[nested]); case "$StringLike": return Match.stringLikeRegexp(v[nested]); + case "$SerializedJson": + return Match.serializedJson(v[nested]); default: return v; } diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/cdk.out b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/cdk.out new file mode 100644 index 0000000000000..145739f539580 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/integ.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/integ.json new file mode 100644 index 0000000000000..9ef53e2c0530b --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "22.0.0", + "testCases": { + "SNS Subscriptions/DefaultTest": { + "stacks": [ + "SnsToSqsStack" + ], + "assertionStack": "SNS Subscriptions/DefaultTest/DeployAssert", + "assertionStackName": "SNSSubscriptionsDefaultTestDeployAssertD77125EB" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/manifest.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/manifest.json new file mode 100644 index 0000000000000..23c2f223c4c8b --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/manifest.json @@ -0,0 +1,215 @@ +{ + "version": "22.0.0", + "artifacts": { + "SnsToSqsStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SnsToSqsStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SnsToSqsStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SnsToSqsStack.template.json", + "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}/1b2f5417b0f02417ad80f41e818ff0917ea4b65ef69016cec3a20d314fe454bc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SnsToSqsStack.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": [ + "SnsToSqsStack.assets" + ], + "metadata": { + "/SnsToSqsStack/MyTopic/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyTopic86869434" + } + ], + "/SnsToSqsStack/Exports/Output{\"Ref\":\"MyTopic86869434\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefMyTopic868694349D03D60F" + } + ], + "/SnsToSqsStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SnsToSqsStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SnsToSqsStack" + }, + "QueueStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "QueueStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "QueueStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "QueueStack.template.json", + "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}/706116cb7bbce00b1ab402aeeaa66b35fc2fef8e57e4192f8ee4747dc5864691.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "QueueStack.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": [ + "SnsToSqsStack", + "QueueStack.assets" + ], + "metadata": { + "/QueueStack/MyQueue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyQueueE6CA6235" + } + ], + "/QueueStack/MyQueue/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyQueuePolicy6BBEDDAC" + } + ], + "/QueueStack/MyQueue/SnsToSqsStackMyTopic3F1182C2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyQueueSnsToSqsStackMyTopic3F1182C25E300A0F" + } + ], + "/QueueStack/Exports/Output{\"Ref\":\"MyQueueE6CA6235\"}": [ + { + "type": "aws:cdk:logicalId", + "data": "ExportsOutputRefMyQueueE6CA623512A57419" + } + ], + "/QueueStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/QueueStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "QueueStack" + }, + "SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SNSSubscriptionsDefaultTestDeployAssertD77125EB": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SNSSubscriptionsDefaultTestDeployAssertD77125EB.template.json", + "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}/9c226b6b87c5f7d528d0a2cdc0627cfb3165de9fb9df32956d25a79356409185.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SNSSubscriptionsDefaultTestDeployAssertD77125EB.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": [ + "SnsToSqsStack", + "QueueStack", + "SNSSubscriptionsDefaultTestDeployAssertD77125EB.assets" + ], + "metadata": { + "/SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsApiCallSNSpublish" + } + ], + "/SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81Role37ABCE73" + } + ], + "/SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F" + } + ], + "/SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsApiCallSQSreceiveMessage" + } + ], + "/SNS Subscriptions/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SNS Subscriptions/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SNS Subscriptions/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/tree.json b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/tree.json new file mode 100644 index 0000000000000..4d3e124a72458 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.js.snapshot/tree.json @@ -0,0 +1,476 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "SnsToSqsStack": { + "id": "SnsToSqsStack", + "path": "SnsToSqsStack", + "children": { + "MyTopic": { + "id": "MyTopic", + "path": "SnsToSqsStack/MyTopic", + "children": { + "Resource": { + "id": "Resource", + "path": "SnsToSqsStack/MyTopic/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Topic", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.CfnTopic", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.Topic", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "SnsToSqsStack/Exports", + "children": { + "Output{\"Ref\":\"MyTopic86869434\"}": { + "id": "Output{\"Ref\":\"MyTopic86869434\"}", + "path": "SnsToSqsStack/Exports/Output{\"Ref\":\"MyTopic86869434\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "SnsToSqsStack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "SnsToSqsStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "QueueStack": { + "id": "QueueStack", + "path": "QueueStack", + "children": { + "MyQueue": { + "id": "MyQueue", + "path": "QueueStack/MyQueue", + "children": { + "Resource": { + "id": "Resource", + "path": "QueueStack/MyQueue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueue", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "QueueStack/MyQueue/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "QueueStack/MyQueue/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::QueuePolicy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "sqs:SendMessage", + "Condition": { + "ArnEquals": { + "aws:SourceArn": { + "Fn::ImportValue": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "sns.amazonaws.com" + }, + "Resource": { + "Fn::GetAtt": [ + "MyQueueE6CA6235", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "queues": [ + { + "Ref": "MyQueueE6CA6235" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueuePolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.QueuePolicy", + "version": "0.0.0" + } + }, + "SnsToSqsStackMyTopic3F1182C2": { + "id": "SnsToSqsStackMyTopic3F1182C2", + "path": "QueueStack/MyQueue/SnsToSqsStackMyTopic3F1182C2", + "children": { + "Resource": { + "id": "Resource", + "path": "QueueStack/MyQueue/SnsToSqsStackMyTopic3F1182C2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SNS::Subscription", + "aws:cdk:cloudformation:props": { + "protocol": "sqs", + "topicArn": { + "Fn::ImportValue": "SnsToSqsStack:ExportsOutputRefMyTopic868694349D03D60F" + }, + "endpoint": { + "Fn::GetAtt": [ + "MyQueueE6CA6235", + "Arn" + ] + }, + "filterPolicy": { + "background": { + "color": [ + "red", + "green", + { + "anything-but": [ + "white", + "orange" + ] + } + ] + }, + "price": [ + { + "numeric": [ + "=", + 100 + ] + }, + { + "numeric": [ + "=", + 200 + ] + }, + { + "numeric": [ + ">", + 500 + ] + }, + { + "numeric": [ + "<", + 1000 + ] + }, + { + "numeric": [ + ">=", + 300, + "<=", + 350 + ] + }, + { + "numeric": [ + ">", + 2000, + "<", + 3000 + ] + } + ] + }, + "filterPolicyScope": "MessageBody" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.CfnSubscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sns.Subscription", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.Queue", + "version": "0.0.0" + } + }, + "Exports": { + "id": "Exports", + "path": "QueueStack/Exports", + "children": { + "Output{\"Ref\":\"MyQueueE6CA6235\"}": { + "id": "Output{\"Ref\":\"MyQueueE6CA6235\"}", + "path": "QueueStack/Exports/Output{\"Ref\":\"MyQueueE6CA6235\"}", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnOutput", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "QueueStack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "QueueStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "SNS Subscriptions": { + "id": "SNS Subscriptions", + "path": "SNS Subscriptions", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "SNS Subscriptions/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "SNS Subscriptions/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "SNS Subscriptions/DefaultTest/DeployAssert", + "children": { + "AwsApiCallSNSpublish": { + "id": "AwsApiCallSNSpublish", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish/Default", + "children": { + "Default": { + "id": "Default", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSNSpublish/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AwsApiCall", + "version": "0.0.0" + } + }, + "SingletonFunction1488541a7b23466481b69b4408076b81": { + "id": "SingletonFunction1488541a7b23466481b69b4408076b81", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81", + "children": { + "Staging": { + "id": "Staging", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/SingletonFunction1488541a7b23466481b69b4408076b81/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "AwsApiCallSQSreceiveMessage": { + "id": "AwsApiCallSQSreceiveMessage", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage", + "children": { + "SdkProvider": { + "id": "SdkProvider", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage/SdkProvider", + "children": { + "AssertionsProvider": { + "id": "AssertionsProvider", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage/SdkProvider/AssertionsProvider", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AssertionsProvider", + "version": "0.0.0" + } + }, + "Default": { + "id": "Default", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage/Default", + "children": { + "Default": { + "id": "Default", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/AwsApiCallSQSreceiveMessage/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.AwsApiCall", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "SNS Subscriptions/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.ts b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.ts new file mode 100644 index 0000000000000..0a6c2ec1b8037 --- /dev/null +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/integ.sns-sqs.ts @@ -0,0 +1,52 @@ +import * as sns from '@aws-cdk/aws-sns'; +import * as sqs from '@aws-cdk/aws-sqs'; +import * as cdk from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; +import * as subs from '../lib'; +class SnsToSqsStack extends cdk.Stack { + topic: sns.Topic; + queue: sqs.Queue; + constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { + super(scope, id, props); + this.topic = new sns.Topic(this, 'MyTopic'); + const queueStack = new cdk.Stack(app, 'QueueStack'); + this.queue = new sqs.Queue(queueStack, 'MyQueue'); + this.topic.addSubscription(new subs.SqsSubscription(this.queue, { + filterPolicyWithMessageBody: { + background: sns.Policy.policy({ + color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({ + allowlist: ['red', 'green'], + denylist: ['white', 'orange'], + })), + }), + price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({ + allowlist: [100, 200], + between: { start: 300, stop: 350 }, + greaterThan: 500, + lessThan: 1000, + betweenStrict: { start: 2000, stop: 3000 }, + })), + }, + })); + } +} +// Beginning of the test suite +const app = new cdk.App(); +const stack = new SnsToSqsStack(app, 'SnsToSqsStack'); +const integTest = new IntegTest(app, 'SNS Subscriptions', { + testCases: [ + stack, + ], +}); +integTest.assertions.awsApiCall('SNS', 'publish', { + Message: '{ background: { color: \'green\' }, price: 200 }', + TopicArn: stack.topic.topicArn, +}); +const message = integTest.assertions.awsApiCall('SQS', 'receiveMessage', { + QueueUrl: stack.queue.queueUrl, + WaitTimeSeconds: 20, +}); +message.expect(ExpectedResult.objectLike({ + Messages: [{ Body: '{color: "green", price: 200}' }], +})); +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-sns-subscriptions/test/subs.test.ts b/packages/@aws-cdk/aws-sns-subscriptions/test/subs.test.ts index 4eed6baf482e1..0b768d668e698 100644 --- a/packages/@aws-cdk/aws-sns-subscriptions/test/subs.test.ts +++ b/packages/@aws-cdk/aws-sns-subscriptions/test/subs.test.ts @@ -1194,13 +1194,13 @@ describe('Restrict sqs decryption feature flag', () => { }); test('lambda subscription', () => { - const fction = new lambda.Function(stack, 'MyFunc', { + const func = new lambda.Function(stack, 'MyFunc', { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.handler', code: lambda.Code.fromInline('exports.handler = function(e, c, cb) { return cb() }'), }); - topic.addSubscription(new subs.LambdaSubscription(fction)); + topic.addSubscription(new subs.LambdaSubscription(func)); Template.fromStack(stack).templateMatches({ 'Resources': { @@ -1305,13 +1305,13 @@ test('lambda subscription, cross region env agnostic', () => { topicName: 'topicName', displayName: 'displayName', }); - const fction = new lambda.Function(lambdaStack, 'MyFunc', { + const func = new lambda.Function(lambdaStack, 'MyFunc', { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.handler', code: lambda.Code.fromInline('exports.handler = function(e, c, cb) { return cb() }'), }); - topic1.addSubscription(new subs.LambdaSubscription(fction)); + topic1.addSubscription(new subs.LambdaSubscription(func)); Template.fromStack(lambdaStack).templateMatches({ 'Resources': { @@ -1419,13 +1419,13 @@ test('lambda subscription, cross region', () => { topicName: 'topicName', displayName: 'displayName', }); - const fction = new lambda.Function(lambdaStack, 'MyFunc', { + const func = new lambda.Function(lambdaStack, 'MyFunc', { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.handler', code: lambda.Code.fromInline('exports.handler = function(e, c, cb) { return cb() }'), }); - topic1.addSubscription(new subs.LambdaSubscription(fction)); + topic1.addSubscription(new subs.LambdaSubscription(func)); Template.fromStack(lambdaStack).templateMatches({ 'Resources': { @@ -1873,13 +1873,13 @@ test('throws with mutliple subscriptions of the same subscriber', () => { }); test('with filter policy', () => { - const fction = new lambda.Function(stack, 'MyFunc', { + const func = new lambda.Function(stack, 'MyFunc', { runtime: lambda.Runtime.NODEJS_14_X, handler: 'index.handler', code: lambda.Code.fromInline('exports.handler = function(e, c, cb) { return cb() }'), }); - topic.addSubscription(new subs.LambdaSubscription(fction, { + topic.addSubscription(new subs.LambdaSubscription(func, { filterPolicy: { color: sns.SubscriptionFilter.stringFilter({ allowlist: ['red'], @@ -1927,6 +1927,53 @@ test('with filter policy', () => { }); }); +test('with filter policy scope MessageBody', () => { + const func = new lambda.Function(stack, 'MyFunc', { + runtime: lambda.Runtime.NODEJS_14_X, + handler: 'index.handler', + code: lambda.Code.fromInline('exports.handler = function(e, c, cb) { return cb() }'), + }); + + topic.addSubscription(new subs.LambdaSubscription(func, { + filterPolicyWithMessageBody: { + color: sns.FilterOrPolicy.policy({ + background: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.stringFilter({ + allowlist: ['red'], + matchPrefixes: ['bl', 'ye'], + })), + }), + size: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.stringFilter({ + denylist: ['small', 'medium'], + })), + }, + })); + + Template.fromStack(stack).hasResourceProperties('AWS::SNS::Subscription', { + 'FilterPolicy': { + 'color': { + 'background': [ + 'red', + { + 'prefix': 'bl', + }, + { + 'prefix': 'ye', + }, + ], + }, + 'size': [ + { + 'anything-but': [ + 'small', + 'medium', + ], + }, + ], + }, + FilterPolicyScope: 'MessageBody', + }); +}); + test('region property is present on an imported topic - sqs', () => { const imported = sns.Topic.fromTopicArn(stack, 'mytopic', 'arn:aws:sns:us-east-1:1234567890:mytopic'); const queue = new sqs.Queue(stack, 'myqueue'); diff --git a/packages/@aws-cdk/aws-sns/README.md b/packages/@aws-cdk/aws-sns/README.md index 5bec12a2a7fcf..0b03c87d5821a 100644 --- a/packages/@aws-cdk/aws-sns/README.md +++ b/packages/@aws-cdk/aws-sns/README.md @@ -93,6 +93,31 @@ myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, { })); ``` +#### Payload-based filtering + +To filter messages based on the payload or body of the message, use the `filterPolicyWithMessageBody` property. This type of filter policy supports creating filters on nested objects. + +Example with a Lambda subscription: + +```ts +import * as lambda from '@aws-cdk/aws-lambda'; + +const myTopic = new sns.Topic(this, 'MyTopic'); +declare const fn: lambda.Function; + +// Lambda should receive only message matching the following conditions on message body: +// color: 'red' or 'orange' +myTopic.addSubscription(new subscriptions.LambdaSubscription(fn, { + filterPolicyWithMessageBody: { + background: sns.FilterOrPolicy.policy({ + color: sns.FilterOrPolicy.filter(sns.SubscriptionFilter.stringFilter({ + allowlist: ['red', 'orange'], + })), + }), + }, +})); +``` + ### Example of Firehose Subscription ```ts diff --git a/packages/@aws-cdk/aws-sns/lib/subscription.ts b/packages/@aws-cdk/aws-sns/lib/subscription.ts index 8d405fc289b76..e8e7d0cde84d9 100644 --- a/packages/@aws-cdk/aws-sns/lib/subscription.ts +++ b/packages/@aws-cdk/aws-sns/lib/subscription.ts @@ -36,7 +36,15 @@ export interface SubscriptionOptions { * * @default - all messages are delivered */ - readonly filterPolicy?: { [attribute: string]: SubscriptionFilter }; + readonly filterPolicy? : { [attribute: string]: SubscriptionFilter }; + + /** + * The filter policy that is applied on the message body. + * To apply a filter policy to the message attributes, use `filterPolicy`. A maximum of one of `filterPolicyWithMessageBody` and `filterPolicy` may be used. + * + * @default - all messages are delivered + */ + readonly filterPolicyWithMessageBody?: { [attribute: string]: FilterOrPolicy }; /** * The region where the topic resides, in the case of cross-region subscriptions @@ -85,6 +93,8 @@ export class Subscription extends Resource { private readonly filterPolicy?: { [attribute: string]: any[] }; + private readonly filterPolicyWithMessageBody? : {[attribute: string]: FilterOrPolicy }; + constructor(scope: Construct, id: string, props: SubscriptionProps) { super(scope, id); @@ -115,20 +125,30 @@ export class Subscription extends Resource { if (total > 150) { throw new Error(`The total combination of values (${total}) must not exceed 150.`); } + } else if (props.filterPolicyWithMessageBody) { + if (Object.keys(props.filterPolicyWithMessageBody).length > 5) { + throw new Error('A filter policy can have a maximum of 5 attribute names.'); + } + this.filterPolicyWithMessageBody = props.filterPolicyWithMessageBody; } if (props.protocol === SubscriptionProtocol.FIREHOSE && !props.subscriptionRoleArn) { throw new Error('Subscription role arn is required field for subscriptions with a firehose protocol.'); } - this.deadLetterQueue = this.buildDeadLetterQueue(props); + // Format filter policy + const filterPolicy = this.filterPolicyWithMessageBody + ? buildFilterPolicyWithMessageBody(this.filterPolicyWithMessageBody) + : this.filterPolicy; + this.deadLetterQueue = this.buildDeadLetterQueue(props); new CfnSubscription(this, 'Resource', { endpoint: props.endpoint, protocol: props.protocol, topicArn: props.topic.topicArn, rawMessageDelivery: props.rawMessageDelivery, - filterPolicy: this.filterPolicy, + filterPolicy, + filterPolicyScope: this.filterPolicyWithMessageBody ? 'MessageBody' : undefined, region: props.region, redrivePolicy: this.buildDeadLetterConfig(this.deadLetterQueue), subscriptionRoleArn: props.subscriptionRoleArn, @@ -215,3 +235,118 @@ export enum SubscriptionProtocol { */ FIREHOSE = 'firehose' } + +function buildFilterPolicyWithMessageBody( + inputObject: { [key: string]: FilterOrPolicy }, + depth = 1, + totalCombinationValues = [1], +): { [key: string]: any } { + const result: { [key: string]: any } = {}; + + for (const [key, filterOrPolicy] of Object.entries(inputObject)) { + if (filterOrPolicy.isPolicy()) { + result[key] = buildFilterPolicyWithMessageBody(filterOrPolicy.policyDoc, depth + 1, totalCombinationValues); + } else if (filterOrPolicy.isFilter()) { + const filter = filterOrPolicy.filterDoc.conditions; + result[key] = filter; + totalCombinationValues[0] *= filter.length * depth; + } + } + + // https://docs.aws.amazon.com/sns/latest/dg/subscription-filter-policy-constraints.html + if (totalCombinationValues[0] > 150) { + throw new Error(`The total combination of values (${totalCombinationValues}) must not exceed 150.`); + } + + return result; +}; + +/** + * The type of the MessageBody at a given key value pair + */ +export enum FilterOrPolicyType { + /** + * The filter of the MessageBody + */ + FILTER, + /** + * A nested key of the MessageBody + */ + POLICY, +} + +/** + * Class for building the FilterPolicy by avoiding union types + */ +export abstract class FilterOrPolicy { + /** + * Filter of MessageBody + * @param filter + * @returns + */ + public static filter(filter: SubscriptionFilter) { + return new Filter(filter); + } + + /** + * Policy of MessageBody + * @param policy + * @returns + */ + public static policy(policy: { [attribute: string]: FilterOrPolicy }) { + return new Policy(policy); + } + + /** + * Type switch for disambiguating between subclasses + */ + abstract readonly type: FilterOrPolicyType; + + /** + * Check if instance is `Policy` type + */ + public isPolicy(): this is Policy { + return this.type === FilterOrPolicyType.POLICY; + } + + /** + * Check if instance is `Filter` type + */ + public isFilter(): this is Filter { + return this.type === FilterOrPolicyType.FILTER; + } +} + +/** + * Filter implementation of FilterOrPolicy + */ +export class Filter extends FilterOrPolicy { + /** + * Type used in DFS buildFilterPolicyWithMessageBody to determine json value type + */ + public readonly type = FilterOrPolicyType.FILTER; + /** + * Policy constructor + * @param filterDoc filter argument to construct + */ + public constructor(public readonly filterDoc: SubscriptionFilter) { + super(); + } +} + +/** + * Policy Implementation of FilterOrPolicy + */ +export class Policy extends FilterOrPolicy { + /** + * Type used in DFS buildFilterPolicyWithMessageBody to determine json value type + */ + public readonly type = FilterOrPolicyType.POLICY; + /** + * Policy constructor + * @param policyDoc policy argument to construct + */ + public constructor(public readonly policyDoc: { [attribute: string]: FilterOrPolicy }) { + super(); + } +} diff --git a/packages/@aws-cdk/aws-sns/test/subscription.test.ts b/packages/@aws-cdk/aws-sns/test/subscription.test.ts index 37359f2769b96..5b5797c186cc0 100644 --- a/packages/@aws-cdk/aws-sns/test/subscription.test.ts +++ b/packages/@aws-cdk/aws-sns/test/subscription.test.ts @@ -153,6 +153,56 @@ describe('Subscription', () => { }); + test('with filter policy and filter policy scope MessageBody', () => { + // GIVEN + const stack = new cdk.Stack(); + const topic = new sns.Topic(stack, 'Topic'); + + // WHEN + new sns.Subscription(stack, 'Subscription', { + endpoint: 'endpoint', + filterPolicyWithMessageBody: { + background: sns.Policy.policy({ + color: sns.Filter.filter(sns.SubscriptionFilter.stringFilter({ + allowlist: ['red', 'green'], + denylist: ['white', 'orange'], + })), + }), + price: sns.Filter.filter(sns.SubscriptionFilter.numericFilter({ + allowlist: [100, 200], + between: { start: 300, stop: 350 }, + greaterThan: 500, + lessThan: 1000, + betweenStrict: { start: 2000, stop: 3000 }, + })), + }, + protocol: sns.SubscriptionProtocol.LAMBDA, + topic, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::SNS::Subscription', { + FilterPolicy: { + background: { + color: [ + 'red', + 'green', + { 'anything-but': ['white', 'orange'] }, + ], + }, + price: [ + { numeric: ['=', 100] }, + { numeric: ['=', 200] }, + { numeric: ['>', 500] }, + { numeric: ['<', 1000] }, + { numeric: ['>=', 300, '<=', 350] }, + { numeric: ['>', 2000, '<', 3000] }, + ], + }, + FilterPolicyScope: 'MessageBody', + }); + }); + test('with numeric filter and 0 values', () => { // GIVEN const stack = new cdk.Stack(); @@ -275,6 +325,24 @@ describe('Subscription', () => { }); + test('throws with more than 150 conditions in a filter policy with filter policy scope set to MessageBody', () => { + // GIVEN + const stack = new cdk.Stack(); + const topic = new sns.Topic(stack, 'Topic'); + + // THEN + expect(() => new sns.Subscription(stack, 'Subscription', { + endpoint: 'endpoint', + protocol: sns.SubscriptionProtocol.LAMBDA, + topic, + filterPolicyWithMessageBody: { + a: sns.Policy.policy({ b: sns.Filter.filter(new sns.SubscriptionFilter([...Array.from(Array(10).keys())])) }), + c: sns.Policy.policy({ d: sns.Filter.filter(new sns.SubscriptionFilter([...Array.from(Array(5).keys())])) }), + }, + })).toThrow(/\(200\) must not exceed 150/); + + }); + test('throws an error when subscription role arn is not entered with firehose subscription protocol', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index 764aaf0c2da92..1e2ebe4bbb600 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -88,7 +88,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "jest": "^27.5.1" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index 073fee55f1dda..b2ca56076dab8 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -228,7 +228,7 @@ state machine role's policy. Use it in the case where the call requires more tha to be executed: ```ts -const detectLabels = new tasks.CallAwsService(stack, 'DetectLabels', { +const detectLabels = new tasks.CallAwsService(this, 'DetectLabels', { service: 'rekognition', action: 'detectLabels', iamResources: ['*'], diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/ecs/run-task.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/ecs/run-task.ts index dd8ed338e68e3..6c02159a56bfe 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/ecs/run-task.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/ecs/run-task.ts @@ -27,6 +27,13 @@ export interface EcsRunTaskProps extends sfn.TaskStateBaseProps { */ readonly taskDefinition: ecs.TaskDefinition; + /** + * The revision number of ECS task definiton family + * + * @default - '$latest' + */ + readonly revisionNumber?: number; + /** * Container setting overrides * @@ -282,7 +289,7 @@ export class EcsRunTask extends sfn.TaskStateBase implements ec2.IConnectable { Resource: integrationResourceArn('ecs', 'runTask', this.integrationPattern), Parameters: sfn.FieldUtils.renderObject({ Cluster: this.props.cluster.clusterArn, - TaskDefinition: this.props.taskDefinition.family, + TaskDefinition: this.props.revisionNumber === undefined ? this.props.taskDefinition.family : `${this.props.taskDefinition.family}:${this.props.revisionNumber.toString()}`, NetworkConfiguration: this.networkConfiguration, Overrides: renderOverrides(this.props.containerOverrides), ...this.props.launchTarget.bind(this, { taskDefinition: this.props.taskDefinition, cluster: this.props.cluster }).parameters, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.assets.json index 43d2aed6b91cd..a5092dbba5075 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.assets.json @@ -1,7 +1,7 @@ { "version": "30.0.0", "files": { - "add92abd33bdedcd7447faa84ea0fe330f8f547f3de2b71052511e602a947aa7": { + "e24a1536363f5a0e085f665d59c23d647a03864eb45d88b8d07e2d0d8e285ee1": { "source": { "path": "aws-sfn-tasks-ecs-fargate-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "add92abd33bdedcd7447faa84ea0fe330f8f547f3de2b71052511e602a947aa7.json", + "objectKey": "e24a1536363f5a0e085f665d59c23d647a03864eb45d88b8d07e2d0d8e285ee1.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.template.json index dace358976d49..d027193b1669d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/aws-sfn-tasks-ecs-fargate-integ.template.json @@ -560,6 +560,22 @@ } } }, + "FargeateTaskSetRevisionNumberSecurityGroup916C9B0B": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber/SecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "VpcId": { + "Ref": "FargateClusterVpc377E8024" + } + } + }, "StateMachineRoleB840431D": { "Type": "AWS::IAM::Role", "Properties": { @@ -775,7 +791,7 @@ "Fn::Join": [ "", [ - "{\"StartAt\":\"Start\",\"States\":{\"Start\":{\"Type\":\"Pass\",\"Result\":{\"SomeKey\":\"SomeValue\",\"Timeout\":900},\"Next\":\"FargateTask\"},\"FargateTask\":{\"End\":true,\"Type\":\"Task\",\"TimeoutSecondsPath\":\"$.Timeout\",\"Resource\":\"arn:", + "{\"StartAt\":\"Start\",\"States\":{\"Start\":{\"Type\":\"Pass\",\"Result\":{\"SomeKey\":\"SomeValue\",\"Timeout\":900},\"Next\":\"FargateTask\"},\"FargateTask\":{\"Next\":\"FargeateTaskSetRevisionNumber\",\"Type\":\"Task\",\"TimeoutSecondsPath\":\"$.Timeout\",\"Resource\":\"arn:", { "Ref": "AWS::Partition" }, @@ -801,7 +817,33 @@ "GroupId" ] }, - "\"]}},\"Overrides\":{\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}}}}" + "\"]}},\"Overrides\":{\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}},\"FargeateTaskSetRevisionNumber\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":states:::ecs:runTask\",\"Parameters\":{\"Cluster\":\"", + { + "Fn::GetAtt": [ + "FargateCluster7CCD5F93", + "Arn" + ] + }, + "\",\"TaskDefinition\":\"awssfntasksecsfargateintegTaskDefD0F4AD10:1\",\"NetworkConfiguration\":{\"AwsvpcConfiguration\":{\"Subnets\":[\"", + { + "Ref": "FargateClusterVpcPrivateSubnet1Subnet9127625F" + }, + "\",\"", + { + "Ref": "FargateClusterVpcPrivateSubnet2Subnet307CEE57" + }, + "\"],\"SecurityGroups\":[\"", + { + "Fn::GetAtt": [ + "FargeateTaskSetRevisionNumberSecurityGroup916C9B0B", + "GroupId" + ] + }, + "\"]}},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}}}}" ] ] } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/manifest.json index d083ec552aba6..92d553548b2a9 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/manifest.json @@ -17,7 +17,7 @@ "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}/add92abd33bdedcd7447faa84ea0fe330f8f547f3de2b71052511e602a947aa7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/e24a1536363f5a0e085f665d59c23d647a03864eb45d88b8d07e2d0d8e285ee1.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -213,6 +213,12 @@ "data": "FargateTaskSecurityGroup0BBB27CB" } ], + "/aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FargeateTaskSetRevisionNumberSecurityGroup916C9B0B" + } + ], "/aws-sfn-tasks-ecs-fargate-integ/StateMachine/Role/Resource": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/tree.json index 0e0a729a20371..4391e121d8b04 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.js.snapshot/tree.json @@ -1016,6 +1016,50 @@ "version": "0.0.0" } }, + "FargeateTaskSetRevisionNumber": { + "id": "FargeateTaskSetRevisionNumber", + "path": "aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber", + "children": { + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-sfn-tasks-ecs-fargate-integ/FargeateTaskSetRevisionNumber/SecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "vpcId": { + "Ref": "FargateClusterVpc377E8024" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.SecurityGroup", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-stepfunctions-tasks.EcsRunTask", + "version": "0.0.0" + } + }, "StateMachine": { "id": "StateMachine", "path": "aws-sfn-tasks-ecs-fargate-integ/StateMachine", @@ -1282,7 +1326,7 @@ "Fn::Join": [ "", [ - "{\"StartAt\":\"Start\",\"States\":{\"Start\":{\"Type\":\"Pass\",\"Result\":{\"SomeKey\":\"SomeValue\",\"Timeout\":900},\"Next\":\"FargateTask\"},\"FargateTask\":{\"End\":true,\"Type\":\"Task\",\"TimeoutSecondsPath\":\"$.Timeout\",\"Resource\":\"arn:", + "{\"StartAt\":\"Start\",\"States\":{\"Start\":{\"Type\":\"Pass\",\"Result\":{\"SomeKey\":\"SomeValue\",\"Timeout\":900},\"Next\":\"FargateTask\"},\"FargateTask\":{\"Next\":\"FargeateTaskSetRevisionNumber\",\"Type\":\"Task\",\"TimeoutSecondsPath\":\"$.Timeout\",\"Resource\":\"arn:", { "Ref": "AWS::Partition" }, @@ -1308,7 +1352,33 @@ "GroupId" ] }, - "\"]}},\"Overrides\":{\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}}}}" + "\"]}},\"Overrides\":{\"ContainerOverrides\":[{\"Name\":\"TheContainer\",\"Environment\":[{\"Name\":\"SOME_KEY\",\"Value.$\":\"$.SomeKey\"}]}]},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}},\"FargeateTaskSetRevisionNumber\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:", + { + "Ref": "AWS::Partition" + }, + ":states:::ecs:runTask\",\"Parameters\":{\"Cluster\":\"", + { + "Fn::GetAtt": [ + "FargateCluster7CCD5F93", + "Arn" + ] + }, + "\",\"TaskDefinition\":\"awssfntasksecsfargateintegTaskDefD0F4AD10:1\",\"NetworkConfiguration\":{\"AwsvpcConfiguration\":{\"Subnets\":[\"", + { + "Ref": "FargateClusterVpcPrivateSubnet1Subnet9127625F" + }, + "\",\"", + { + "Ref": "FargateClusterVpcPrivateSubnet2Subnet307CEE57" + }, + "\"],\"SecurityGroups\":[\"", + { + "Fn::GetAtt": [ + "FargeateTaskSetRevisionNumberSecurityGroup916C9B0B", + "GroupId" + ] + }, + "\"]}},\"LaunchType\":\"FARGATE\",\"PlatformVersion\":\"1.4.0\"}}}}" ] ] } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.ts index 9863b0d9d688e..cbee6f54f03c7 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/integ.fargate-run-task.ts @@ -55,6 +55,15 @@ const definition = new sfn.Pass(stack, 'Start', { }), taskTimeout: sfn.Timeout.at('$.Timeout'), }), +).next( + new tasks.EcsRunTask(stack, 'FargeateTaskSetRevisionNumber', { + cluster, + taskDefinition, + revisionNumber: 1, + launchTarget: new tasks.EcsFargateLaunchTarget({ + platformVersion: ecs.FargatePlatformVersion.VERSION1_4, + }), + }), ); const sm = new sfn.StateMachine(stack, 'StateMachine', { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/run-tasks.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/run-tasks.test.ts index 88a1c91af2d2a..a4074a7869d03 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/run-tasks.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/ecs/run-tasks.test.ts @@ -563,3 +563,72 @@ test('Running a task with WAIT_FOR_TASK_TOKEN and task token in environment', () taskDefinition, })).not.toThrow(); }); + +test('Set revision number of ECS task denition family', () => { + // When + const taskDefinition = new ecs.TaskDefinition(stack, 'TD', { + memoryMiB: '512', + cpu: '256', + compatibility: ecs.Compatibility.FARGATE, + }); + taskDefinition.addContainer('TheContainer', { + image: ecs.ContainerImage.fromRegistry('foo/bar'), + memoryLimitMiB: 256, + }); + const runTask = new tasks.EcsRunTask(stack, 'task', { + cluster, + taskDefinition: taskDefinition, + revisionNumber: 1, + launchTarget: new tasks.EcsFargateLaunchTarget(), + }); + + // Then + expect(stack.resolve(runTask.toStateJson())).toEqual( + { + End: true, + Parameters: { + Cluster: { + 'Fn::GetAtt': [ + 'ClusterEB0386A7', + 'Arn', + ], + }, + LaunchType: 'FARGATE', + NetworkConfiguration: { + AwsvpcConfiguration: { + SecurityGroups: [ + { + 'Fn::GetAtt': [ + 'taskSecurityGroup28F0D539', + 'GroupId', + ], + }, + ], + Subnets: [ + { + Ref: 'VpcPrivateSubnet1Subnet536B997A', + }, + { + Ref: 'VpcPrivateSubnet2Subnet3788AAA1', + }, + ], + }, + }, + TaskDefinition: 'TD:1', + }, + Resource: { + 'Fn::Join': [ + '', + [ + 'arn:', + { + 'Ref': 'AWS::Partition', + }, + ':states:::ecs:runTask', + ], + ], + }, + Type: 'Task', + }, + ); +}); diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json index 48c34232a2aca..11c7ad9c32e0b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac": { + "ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7": { "source": { "path": "awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json", + "objectKey": "ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc": { + "2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f": { "source": { "path": "awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json", + "objectKey": "2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5": { + "517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da": { "source": { "path": "aws-stepfunctions-tasks-eks-call-integ-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5.json", + "objectKey": "517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json index 45b2cdc39c34c..0c46cdd0cd81b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/aws-stepfunctions-tasks-eks-call-integ-test.template.json @@ -996,7 +996,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json" + "/ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json" ] ] }, @@ -1031,7 +1031,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json" + "/2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json index 3e37b187392c6..1d6357d705d4f 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegDefaultTestDeployAssert2DF4AD1E.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json index 504a30f0d65b5..c5b6a97520a15 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksClusterResourceProvider412BC189.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json index c48d6b8e26afb..3dd91320ca7ac 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/awsstepfunctionstasksekscallintegtestawscdkawseksKubectlProvider65D285A0.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json index b2e0b69af5538..6b97c3e72a57f 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-eks-call-integ/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json index a2c620649373b..b5f90a2e3ec5a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-eks-call-integ-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/9a5ccbde1de37acad0d352a3fc3a1b1615c04d758008522a66e1fb1c087310a5.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/517638b14b3968f2d1b04504c73efba2af37b71a925d21253557359ea48ac5da.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json index a80b88576947a..125ae02f335e2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.js.snapshot/tree.json @@ -1020,7 +1020,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1486,7 +1486,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1659,7 +1659,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2500,7 +2500,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2557,7 +2557,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/8d5969a90e2e720721ef401f4a46a8d1c61cb13e72e729538898ef747c3641ac.json" + "/ce676dd00b6b83bd39d97745ba4264d3db3b983f6c1862784cb9a0c8b02466e7.json" ] ] }, @@ -2579,7 +2579,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2656,6 +2656,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2755,7 +2767,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3225,7 +3237,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2a398731934eca1054c33c88ad3e4128309643d200092ff00c7605e8965451cc.json" + "/2f6232262f61ee4d0aaf7ccee2de42f40c122cd7d534b88592e9543db954213f.json" ] ] }, @@ -3265,7 +3277,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "Role": { @@ -3422,7 +3434,7 @@ "path": "aws-stepfunctions-tasks-eks-call-integ/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -3468,7 +3480,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js deleted file mode 100644 index 1d08e9d7b865b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ /dev/null @@ -1,273 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - } - ; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size && [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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SSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py deleted file mode 100644 index a7b26b264118b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. - # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json index 5264c7c63073b..4782f75a558a7 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -79,7 +79,7 @@ } } }, - "885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4": { + "37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8": { "source": { "path": "awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json", "packaging": "file" @@ -87,12 +87,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json", + "objectKey": "37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf": { + "1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62": { "source": { "path": "awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json", "packaging": "file" @@ -100,12 +100,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json", + "objectKey": "1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6": { + "8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-all-services-test.template.json", "packaging": "file" @@ -113,7 +113,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6.json", + "objectKey": "8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json index c53c4476e59d3..099bb579ed7c2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/aws-stepfunctions-tasks-emr-containers-all-services-test.template.json @@ -921,7 +921,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json" + "/37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json" ] ] }, @@ -956,7 +956,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json" + "/1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json index 7eb8c3eed5b01..2bb5586770fdb 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicesDefaultTestDeployAssertE09C88B0.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json index a348b53b52164..d7886f59f5435 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksClusterResourceProvider6985269B.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json index 3f50a0ca1ad50..a453d8d206b27 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/awsstepfunctionstasksemrcontainersallservicestestawscdkawseksKubectlProviderD9DFA1E3.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json index ec0222b3a4e26..c88b2f61414ea 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-emr-containers-all-services/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json index 40f081541857e..e932aaf072a48 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-emr-containers-all-services-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/fb60dad6258f36a2ef48b66ae220c4f7de6a319c89b75b23610f2803cbe36eb6.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8662d9a0c24ddd076682929e683932742480ec48e502a42fa69b66a32863c925.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json index bcfbe83192ddd..08fe935f66e6a 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.job-submission-workflow.js.snapshot/tree.json @@ -960,7 +960,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1426,7 +1426,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1599,7 +1599,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2440,7 +2440,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2497,7 +2497,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/885e8871bf0bbc96a133a56f1f7cdee17dd902d8967fd326b61d6f8b8901b9b4.json" + "/37b9bc4f34c2af7d98cff20053a09be46c63d26f7c9951e19230de787314a5f8.json" ] ] }, @@ -2519,7 +2519,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2596,6 +2596,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2695,7 +2707,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3165,7 +3177,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/64935f5256b8a6a408fe03c069615fe7d74eedd9e98cfab64bfc6de60e4207bf.json" + "/1c293083c7ca2a85b9971a56b827528655c982c7cd525788c11f25281c50ff62.json" ] ] }, @@ -3205,7 +3217,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "JobExecutionRole": { @@ -3748,7 +3760,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-all-services/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -3794,7 +3806,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js new file mode 100644 index 0000000000000..c9dc1b8d2c19a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.js @@ -0,0 +1,273 @@ +"use strict"; +/* eslint-disable no-console */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ClusterResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_CLUSTER_NAME_LEN = 100; +class ClusterResourceHandler extends common_1.ResourceHandler { + constructor(eks, event) { + super(eks, event); + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + return this.physicalResourceId; + } + // ------ + // CREATE + // ------ + async onCreate() { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + const clusterName = this.newProps.name || this.generateClusterName(); + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + return { + PhysicalResourceId: resp.cluster.name, + }; + } + async isCreateComplete() { + return this.isActive(); + } + // ------ + // DELETE + // ------ + async onDelete() { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } + catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } + else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + async isDeleteComplete() { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } + catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + console.log('describeCluster error:', e); + throw e; + } + return { + IsComplete: false, + }; + } + // ------ + // UPDATE + // ------ + async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + return this.onCreate(); + } + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + return this.updateClusterVersion(this.newProps.version); + } + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + if (updates.updateLogging || updates.updateAccess) { + const config = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + } + ; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + return { EksUpdateId: updateResponse.update?.id }; + } + // no updates + return; + } + async isUpdateComplete() { + console.log('isUpdateComplete'); + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + return this.isActive(); + } + async updateClusterVersion(newVersion) { + console.log(`updating cluster version to ${newVersion}`); + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + async isActive() { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } + else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } + else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + async isEksUpdateComplete(eksUpdateId) { + this.log({ isEksUpdateComplete: eksUpdateId }); + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + this.log({ describeUpdateResponse }); + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} +exports.ClusterResourceHandler = ClusterResourceHandler; +function parseProps(props) { + const parsed = props?.Config ?? {}; + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + return parsed; +} +function analyzeUpdate(oldProps, newProps) { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} +function setsEqual(first, second) { + return first.size === second.size && [...first].every((e) => second.has(e)); +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJ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LENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcz8uc29ydCgpKSAhPT0gSlNPTi5zdHJpbmdpZnkob2xkVnBjUHJvcHMuc3VibmV0SWRzPy5zb3J0KCkpIHx8XG4gICAgICBKU09OLnN0cmluZ2lmeShuZXdWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzPy5zb3J0KCkpLFxuICAgIHVwZGF0ZUFjY2VzczpcbiAgICAgIG5ld1ZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQcml2YXRlQWNjZXNzIHx8XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFB1YmxpY0FjY2VzcyAhPT0gb2xkVnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgfHxcbiAgICAgICFzZXRzRXF1YWwobmV3UHVibGljQWNjZXNzQ2lkcnMsIG9sZFB1YmxpY0FjY2Vzc0NpZHJzKSxcbiAgICByZXBsYWNlUm9sZTogbmV3UHJvcHMucm9sZUFybiAhPT0gb2xkUHJvcHMucm9sZUFybixcbiAgICB1cGRhdGVWZXJzaW9uOiBuZXdQcm9wcy52ZXJzaW9uICE9PSBvbGRQcm9wcy52ZXJzaW9uLFxuICAgIHVwZGF0ZUVuY3J5cHRpb246IEpTT04uc3RyaW5naWZ5KG5ld0VuYykgIT09IEpTT04uc3RyaW5naWZ5KG9sZEVuYyksXG4gICAgdXBkYXRlTG9nZ2luZzogSlNPTi5zdHJpbmdpZnkobmV3UHJvcHMubG9nZ2luZykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFByb3BzLmxvZ2dpbmcpLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzZXRzRXF1YWwoZmlyc3Q6IFNldDxzdHJpbmc+LCBzZWNvbmQ6IFNldDxzdHJpbmc+KSB7XG4gIHJldHVybiBmaXJzdC5zaXplID09PSBzZWNvbmQuc2l6ZSAmJiBbLi4uZmlyc3RdLmV2ZXJ5KChlOiBzdHJpbmcpID0+IHNlY29uZC5oYXMoZSkpO1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts new file mode 100644 index 0000000000000..4b7fdda6d1dd1 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/cluster.ts @@ -0,0 +1,344 @@ +/* eslint-disable no-console */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { EksClient, ResourceEvent, ResourceHandler } from './common'; + +const MAX_CLUSTER_NAME_LEN = 100; + +export class ClusterResourceHandler extends ResourceHandler { + public get clusterName() { + if (!this.physicalResourceId) { + throw new Error('Cannot determine cluster name without physical resource ID'); + } + + return this.physicalResourceId; + } + + private readonly newProps: aws.EKS.CreateClusterRequest; + private readonly oldProps: Partial; + + constructor(eks: EksClient, event: ResourceEvent) { + super(eks, event); + + this.newProps = parseProps(this.event.ResourceProperties); + this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; + } + + // ------ + // CREATE + // ------ + + protected async onCreate(): Promise { + console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); + if (!this.newProps.roleArn) { + throw new Error('"roleArn" is required'); + } + + const clusterName = this.newProps.name || this.generateClusterName(); + + const resp = await this.eks.createCluster({ + ...this.newProps, + name: clusterName, + }); + + if (!resp.cluster) { + throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); + } + + return { + PhysicalResourceId: resp.cluster.name, + }; + } + + protected async isCreateComplete() { + return this.isActive(); + } + + // ------ + // DELETE + // ------ + + protected async onDelete(): Promise { + console.log(`onDelete: deleting cluster ${this.clusterName}`); + try { + await this.eks.deleteCluster({ name: this.clusterName }); + } catch (e) { + if (e.code !== 'ResourceNotFoundException') { + throw e; + } else { + console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); + } + } + return { + PhysicalResourceId: this.clusterName, + }; + } + + protected async isDeleteComplete(): Promise { + console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); + + try { + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); + } catch (e) { + if (e.code === 'ResourceNotFoundException') { + console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); + return { IsComplete: true }; + } + + console.log('describeCluster error:', e); + throw e; + } + + return { + IsComplete: false, + }; + } + + // ------ + // UPDATE + // ------ + + protected async onUpdate() { + const updates = analyzeUpdate(this.oldProps, this.newProps); + console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); + + // updates to encryption config is not supported + if (updates.updateEncryption) { + throw new Error('Cannot update cluster encryption configuration'); + } + + // if there is an update that requires replacement, go ahead and just create + // a new cluster with the new config. The old cluster will automatically be + // deleted by cloudformation upon success. + if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { + + // if we are replacing this cluster and the cluster has an explicit + // physical name, the creation of the new cluster will fail with "there is + // already a cluster with that name". this is a common behavior for + // CloudFormation resources that support specifying a physical name. + if (this.oldProps.name === this.newProps.name && this.oldProps.name) { + throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); + } + + return this.onCreate(); + } + + // if a version update is required, issue the version update + if (updates.updateVersion) { + if (!this.newProps.version) { + throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); + } + + return this.updateClusterVersion(this.newProps.version); + } + + if (updates.updateLogging && updates.updateAccess) { + throw new Error('Cannot update logging and access at the same time'); + } + + if (updates.updateLogging || updates.updateAccess) { + const config: aws.EKS.UpdateClusterConfigRequest = { + name: this.clusterName, + }; + if (updates.updateLogging) { + config.logging = this.newProps.logging; + }; + if (updates.updateAccess) { + // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: + // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) + // will fail, therefore we take only the access fields explicitly + config.resourcesVpcConfig = { + endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, + endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, + publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, + }; + } + const updateResponse = await this.eks.updateClusterConfig(config); + + return { EksUpdateId: updateResponse.update?.id }; + } + + // no updates + return; + } + + protected async isUpdateComplete() { + console.log('isUpdateComplete'); + + // if this is an EKS update, we will monitor the update event itself + if (this.event.EksUpdateId) { + const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); + if (!complete) { + return { IsComplete: false }; + } + + // fall through: if the update is done, we simply delegate to isActive() + // in order to extract attributes and state from the cluster itself, which + // is supposed to be in an ACTIVE state after the update is complete. + } + + return this.isActive(); + } + + private async updateClusterVersion(newVersion: string) { + console.log(`updating cluster version to ${newVersion}`); + + // update-cluster-version will fail if we try to update to the same version, + // so skip in this case. + const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; + if (cluster?.version === newVersion) { + console.log(`cluster already at version ${cluster.version}, skipping version update`); + return; + } + + const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); + return { EksUpdateId: updateResponse.update?.id }; + } + + private async isActive(): Promise { + console.log('waiting for cluster to become ACTIVE'); + const resp = await this.eks.describeCluster({ name: this.clusterName }); + console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); + const cluster = resp.cluster; + + // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are + // not complete. note that the custom resource provider framework forbids + // returning attributes (Data) if isComplete is false. + if (cluster?.status === 'FAILED') { + // not very informative, unfortunately the response doesn't contain any error + // information :\ + throw new Error('Cluster is in a FAILED status'); + } else if (cluster?.status !== 'ACTIVE') { + return { + IsComplete: false, + }; + } else { + return { + IsComplete: true, + Data: { + Name: cluster.name, + Endpoint: cluster.endpoint, + Arn: cluster.arn, + + // IMPORTANT: CFN expects that attributes will *always* have values, + // so return an empty string in case the value is not defined. + // Otherwise, CFN will throw with `Vendor response doesn't contain + // XXXX key`. + + CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', + ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', + OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', + OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url + + // We can safely return the first item from encryption configuration array, because it has a limit of 1 item + // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig + EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', + }, + }; + } + } + + private async isEksUpdateComplete(eksUpdateId: string) { + this.log({ isEksUpdateComplete: eksUpdateId }); + + const describeUpdateResponse = await this.eks.describeUpdate({ + name: this.clusterName, + updateId: eksUpdateId, + }); + + this.log({ describeUpdateResponse }); + + if (!describeUpdateResponse.update) { + throw new Error(`unable to describe update with id "${eksUpdateId}"`); + } + + switch (describeUpdateResponse.update.status) { + case 'InProgress': + return false; + case 'Successful': + return true; + case 'Failed': + case 'Cancelled': + throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); + default: + throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); + } + } + + private generateClusterName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } +} + +function parseProps(props: any): aws.EKS.CreateClusterRequest { + + const parsed = props?.Config ?? {}; + + // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. + // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' + + if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; + } + + if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { + parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; + } + + if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { + parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; + } + + return parsed; + +} + +interface UpdateMap { + replaceName: boolean; // name + replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds + replaceRole: boolean; // roleArn + + updateVersion: boolean; // version + updateLogging: boolean; // logging + updateEncryption: boolean; // encryption (cannot be updated) + updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess +} + +function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { + console.log('old props: ', JSON.stringify(oldProps)); + console.log('new props: ', JSON.stringify(newProps)); + + const newVpcProps = newProps.resourcesVpcConfig || {}; + const oldVpcProps = oldProps.resourcesVpcConfig || {}; + + const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); + const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); + const newEnc = newProps.encryptionConfig || {}; + const oldEnc = oldProps.encryptionConfig || {}; + + return { + replaceName: newProps.name !== oldProps.name, + replaceVpc: + JSON.stringify(newVpcProps.subnetIds?.sort()) !== JSON.stringify(oldVpcProps.subnetIds?.sort()) || + JSON.stringify(newVpcProps.securityGroupIds?.sort()) !== JSON.stringify(oldVpcProps.securityGroupIds?.sort()), + updateAccess: + newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || + newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || + !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), + replaceRole: newProps.roleArn !== oldProps.roleArn, + updateVersion: newProps.version !== oldProps.version, + updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), + updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), + }; +} + +function setsEqual(first: Set, second: Set) { + return first.size === second.size && [...first].every((e: string) => second.has(e)); +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/common.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js new file mode 100644 index 0000000000000..5dbf4000517e4 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ResourceHandler = void 0; +class ResourceHandler { + constructor(eks, event) { + this.eks = eks; + this.requestType = event.RequestType; + this.requestId = event.RequestId; + this.logicalResourceId = event.LogicalResourceId; + this.physicalResourceId = event.PhysicalResourceId; + this.event = event; + const roleToAssume = event.ResourceProperties.AssumeRoleArn; + if (!roleToAssume) { + throw new Error('AssumeRoleArn must be provided'); + } + eks.configureAssumeRole({ + RoleArn: roleToAssume, + RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, + }); + } + onEvent() { + switch (this.requestType) { + case 'Create': return this.onCreate(); + case 'Update': return this.onUpdate(); + case 'Delete': return this.onDelete(); + } + throw new Error(`Invalid request type ${this.requestType}`); + } + isComplete() { + switch (this.requestType) { + case 'Create': return this.isCreateComplete(); + case 'Update': return this.isUpdateComplete(); + case 'Delete': return this.isDeleteComplete(); + } + throw new Error(`Invalid request type ${this.requestType}`); + } + log(x) { + // eslint-disable-next-line no-console + console.log(JSON.stringify(x, undefined, 2)); + } +} +exports.ResourceHandler = ResourceHandler; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29tbW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSxNQUFzQixlQUFlO0lBT25DLFlBQStCLEdBQWMsRUFBRSxLQUFvQjtRQUFwQyxRQUFHLEdBQUgsR0FBRyxDQUFXO1FBQzNDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNyQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQztRQUNqRCxJQUFJLENBQUMsa0JBQWtCLEdBQUksS0FBYSxDQUFDLGtCQUFrQixDQUFDO1FBQzVELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBRW5CLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxHQUFHLENBQUMsbUJBQW1CLENBQUM7WUFDdEIsT0FBTyxFQUFFLFlBQVk7WUFDckIsZUFBZSxFQUFFLHFCQUFxQixJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7U0FDM0UsQ0FBQyxDQUFDO0tBQ0o7SUFFTSxPQUFPO1FBQ1osUUFBUSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3hCLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDdEMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN0QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1NBQ3ZDO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7S0FDN0Q7SUFFTSxVQUFVO1FBQ2YsUUFBUSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3hCLEtBQUssUUFBUSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM5QyxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDOUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1NBQy9DO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7S0FDN0Q7SUFFUyxHQUFHLENBQUMsQ0FBTTtRQUNsQixzQ0FBc0M7UUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUM5QztDQVFGO0FBeERELDBDQXdEQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCB7IElzQ29tcGxldGVSZXNwb25zZSwgT25FdmVudFJlc3BvbnNlIH0gZnJvbSAnQGF3cy1jZGsvY3VzdG9tLXJlc291cmNlcy9saWIvcHJvdmlkZXItZnJhbWV3b3JrL3R5cGVzJztcblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVrc1VwZGF0ZUlkIHtcbiAgLyoqXG4gICAqIElmIHRoaXMgZmllbGQgaXMgaW5jbHVkZWQgaW4gYW4gZXZlbnQgcGFzc2VkIHRvIFwiSXNDb21wbGV0ZVwiLCBpdCBtZWFucyB3ZVxuICAgKiBpbml0aWF0ZWQgYW4gRUtTIHVwZGF0ZSB0aGF0IHNob3VsZCBiZSBtb25pdG9yZWQgdXNpbmcgZWtzOkRlc2NyaWJlVXBkYXRlXG4gICAqIGluc3RlYWQgb2YganVzdCBsb29raW5nIGF0IHRoZSBjbHVzdGVyIHN0YXR1cy5cbiAgICovXG4gIEVrc1VwZGF0ZUlkPzogc3RyaW5nXG59XG5cbmV4cG9ydCB0eXBlIFJlc291cmNlRXZlbnQgPSBBV1NMYW1iZGEuQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50ICYgRWtzVXBkYXRlSWQ7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZXNvdXJjZUhhbmRsZXIge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVxdWVzdElkOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSBsb2dpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVxdWVzdFR5cGU6ICdDcmVhdGUnIHwgJ1VwZGF0ZScgfCAnRGVsZXRlJztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGV2ZW50OiBSZXNvdXJjZUV2ZW50O1xuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCByZWFkb25seSBla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICB0aGlzLnJlcXVlc3RUeXBlID0gZXZlbnQuUmVxdWVzdFR5cGU7XG4gICAgdGhpcy5yZXF1ZXN0SWQgPSBldmVudC5SZXF1ZXN0SWQ7XG4gICAgdGhpcy5sb2dpY2FsUmVzb3VyY2VJZCA9IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkO1xuICAgIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkID0gKGV2ZW50IGFzIGFueSkuUGh5c2ljYWxSZXNvdXJjZUlkO1xuICAgIHRoaXMuZXZlbnQgPSBldmVudDtcblxuICAgIGNvbnN0IHJvbGVUb0Fzc3VtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5Bc3N1bWVSb2xlQXJuO1xuICAgIGlmICghcm9sZVRvQXNzdW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Fzc3VtZVJvbGVBcm4gbXVzdCBiZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGVrcy5jb25maWd1cmVBc3N1bWVSb2xlKHtcbiAgICAgIFJvbGVBcm46IHJvbGVUb0Fzc3VtZSxcbiAgICAgIFJvbGVTZXNzaW9uTmFtZTogYEFXU0NESy5FS1NDbHVzdGVyLiR7dGhpcy5yZXF1ZXN0VHlwZX0uJHt0aGlzLnJlcXVlc3RJZH1gLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uRXZlbnQoKSB7XG4gICAgc3dpdGNoICh0aGlzLnJlcXVlc3RUeXBlKSB7XG4gICAgICBjYXNlICdDcmVhdGUnOiByZXR1cm4gdGhpcy5vbkNyZWF0ZSgpO1xuICAgICAgY2FzZSAnVXBkYXRlJzogcmV0dXJuIHRoaXMub25VcGRhdGUoKTtcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6IHJldHVybiB0aGlzLm9uRGVsZXRlKCk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlcXVlc3QgdHlwZSAke3RoaXMucmVxdWVzdFR5cGV9YCk7XG4gIH1cblxuICBwdWJsaWMgaXNDb21wbGV0ZSgpIHtcbiAgICBzd2l0Y2ggKHRoaXMucmVxdWVzdFR5cGUpIHtcbiAgICAgIGNhc2UgJ0NyZWF0ZSc6IHJldHVybiB0aGlzLmlzQ3JlYXRlQ29tcGxldGUoKTtcbiAgICAgIGNhc2UgJ1VwZGF0ZSc6IHJldHVybiB0aGlzLmlzVXBkYXRlQ29tcGxldGUoKTtcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6IHJldHVybiB0aGlzLmlzRGVsZXRlQ29tcGxldGUoKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmVxdWVzdCB0eXBlICR7dGhpcy5yZXF1ZXN0VHlwZX1gKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBsb2coeDogYW55KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh4LCB1bmRlZmluZWQsIDIpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBvbkRlbGV0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZSB8IHZvaWQ+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgb25VcGRhdGUoKTogUHJvbWlzZTwoT25FdmVudFJlc3BvbnNlICYgRWtzVXBkYXRlSWQpIHwgdm9pZD47XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBhc3luYyBpc0NyZWF0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPjtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IGFzeW5jIGlzRGVsZXRlQ29tcGxldGUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+O1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpOiBQcm9taXNlPElzQ29tcGxldGVSZXNwb25zZT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWtzQ2xpZW50IHtcbiAgY29uZmlndXJlQXNzdW1lUm9sZShyZXF1ZXN0OiBhd3MuU1RTLkFzc3VtZVJvbGVSZXF1ZXN0KTogdm9pZDtcbiAgY3JlYXRlQ2x1c3RlcihyZXF1ZXN0OiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXNwb25zZT47XG4gIGRlbGV0ZUNsdXN0ZXIocmVxdWVzdDogYXdzLkVLUy5EZWxldGVDbHVzdGVyUmVxdWVzdCk6IFByb21pc2U8YXdzLkVLUy5EZWxldGVDbHVzdGVyUmVzcG9uc2U+O1xuICBkZXNjcmliZUNsdXN0ZXIocmVxdWVzdDogYXdzLkVLUy5EZXNjcmliZUNsdXN0ZXJSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlQ2x1c3RlclJlc3BvbnNlPjtcbiAgdXBkYXRlQ2x1c3RlckNvbmZpZyhyZXF1ZXN0OiBhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJDb25maWdSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJDb25maWdSZXNwb25zZT47XG4gIHVwZGF0ZUNsdXN0ZXJWZXJzaW9uKHJlcXVlc3Q6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlclZlcnNpb25SZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLlVwZGF0ZUNsdXN0ZXJWZXJzaW9uUmVzcG9uc2U+O1xuICBkZXNjcmliZVVwZGF0ZShyZXE6IGF3cy5FS1MuRGVzY3JpYmVVcGRhdGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlVXBkYXRlUmVzcG9uc2U+O1xuICBjcmVhdGVGYXJnYXRlUHJvZmlsZShyZXF1ZXN0OiBhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCk6IFByb21pc2U8YXdzLkVLUy5DcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlPjtcbiAgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZShyZXF1ZXN0OiBhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZT47XG4gIGRlbGV0ZUZhcmdhdGVQcm9maWxlKHJlcXVlc3Q6IGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0KTogUHJvbWlzZTxhd3MuRUtTLkRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2U+O1xufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts new file mode 100644 index 0000000000000..21cf958df5a68 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/common.ts @@ -0,0 +1,87 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; + +export interface EksUpdateId { + /** + * If this field is included in an event passed to "IsComplete", it means we + * initiated an EKS update that should be monitored using eks:DescribeUpdate + * instead of just looking at the cluster status. + */ + EksUpdateId?: string +} + +export type ResourceEvent = AWSLambda.CloudFormationCustomResourceEvent & EksUpdateId; + +export abstract class ResourceHandler { + protected readonly requestId: string; + protected readonly logicalResourceId: string; + protected readonly requestType: 'Create' | 'Update' | 'Delete'; + protected readonly physicalResourceId?: string; + protected readonly event: ResourceEvent; + + constructor(protected readonly eks: EksClient, event: ResourceEvent) { + this.requestType = event.RequestType; + this.requestId = event.RequestId; + this.logicalResourceId = event.LogicalResourceId; + this.physicalResourceId = (event as any).PhysicalResourceId; + this.event = event; + + const roleToAssume = event.ResourceProperties.AssumeRoleArn; + if (!roleToAssume) { + throw new Error('AssumeRoleArn must be provided'); + } + + eks.configureAssumeRole({ + RoleArn: roleToAssume, + RoleSessionName: `AWSCDK.EKSCluster.${this.requestType}.${this.requestId}`, + }); + } + + public onEvent() { + switch (this.requestType) { + case 'Create': return this.onCreate(); + case 'Update': return this.onUpdate(); + case 'Delete': return this.onDelete(); + } + + throw new Error(`Invalid request type ${this.requestType}`); + } + + public isComplete() { + switch (this.requestType) { + case 'Create': return this.isCreateComplete(); + case 'Update': return this.isUpdateComplete(); + case 'Delete': return this.isDeleteComplete(); + } + + throw new Error(`Invalid request type ${this.requestType}`); + } + + protected log(x: any) { + // eslint-disable-next-line no-console + console.log(JSON.stringify(x, undefined, 2)); + } + + protected abstract async onCreate(): Promise; + protected abstract async onDelete(): Promise; + protected abstract async onUpdate(): Promise<(OnEventResponse & EksUpdateId) | void>; + protected abstract async isCreateComplete(): Promise; + protected abstract async isDeleteComplete(): Promise; + protected abstract async isUpdateComplete(): Promise; +} + +export interface EksClient { + configureAssumeRole(request: aws.STS.AssumeRoleRequest): void; + createCluster(request: aws.EKS.CreateClusterRequest): Promise; + deleteCluster(request: aws.EKS.DeleteClusterRequest): Promise; + describeCluster(request: aws.EKS.DescribeClusterRequest): Promise; + updateClusterConfig(request: aws.EKS.UpdateClusterConfigRequest): Promise; + updateClusterVersion(request: aws.EKS.UpdateClusterVersionRequest): Promise; + describeUpdate(req: aws.EKS.DescribeUpdateRequest): Promise; + createFargateProfile(request: aws.EKS.CreateFargateProfileRequest): Promise; + describeFargateProfile(request: aws.EKS.DescribeFargateProfileRequest): Promise; + deleteFargateProfile(request: aws.EKS.DeleteFargateProfileRequest): Promise; +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/consts.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts new file mode 100644 index 0000000000000..bae91b9ba79ca --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/consts.ts @@ -0,0 +1,2 @@ +export const CLUSTER_RESOURCE_TYPE = 'Custom::AWSCDK-EKS-Cluster'; +export const FARGATE_PROFILE_RESOURCE_TYPE = 'Custom::AWSCDK-EKS-FargateProfile'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/fargate.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js new file mode 100644 index 0000000000000..f74022f9be26d --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.js @@ -0,0 +1,102 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FargateProfileResourceHandler = void 0; +const common_1 = require("./common"); +const MAX_NAME_LEN = 63; +class FargateProfileResourceHandler extends common_1.ResourceHandler { + async onCreate() { + const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); + const createFargateProfile = { + fargateProfileName, + ...this.event.ResourceProperties.Config, + }; + this.log({ createFargateProfile }); + const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); + this.log({ createFargateProfileResponse }); + if (!createFargateProfileResponse.fargateProfile) { + throw new Error('invalid CreateFargateProfile response'); + } + return { + PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, + Data: { + fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, + }, + }; + } + async onDelete() { + if (!this.physicalResourceId) { + throw new Error('Cannot delete a profile without a physical id'); + } + const deleteFargateProfile = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + this.log({ deleteFargateProfile }); + const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); + this.log({ deleteFargateProfileResponse }); + return; + } + async onUpdate() { + // all updates require a replacement. as long as name is generated, we are + // good. if name is explicit, update will fail, which is common when trying + // to replace cfn resources with explicit physical names + return this.onCreate(); + } + async isCreateComplete() { + return this.isUpdateComplete(); + } + async isUpdateComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'ACTIVE', + }; + } + async isDeleteComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'NOT_FOUND', + }; + } + /** + * Generates a fargate profile name. + */ + generateProfileName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } + /** + * Queries the Fargate profile's current status and returns the status or + * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). + */ + async queryStatus() { + if (!this.physicalResourceId) { + throw new Error('Unable to determine status for fargate profile without a resource name'); + } + const describeFargateProfile = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + try { + this.log({ describeFargateProfile }); + const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); + this.log({ describeFargateProfileResponse }); + const status = describeFargateProfileResponse.fargateProfile?.status; + if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { + throw new Error(status); + } + return status; + } + catch (describeFargateProfileError) { + if (describeFargateProfileError.code === 'ResourceNotFoundException') { + this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); + return 'NOT_FOUND'; + } + this.log({ describeFargateProfileError }); + throw describeFargateProfileError; + } + } +} +exports.FargateProfileResourceHandler = FargateProfileResourceHandler; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZhcmdhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUNBQTJDO0FBRTNDLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUV4QixNQUFhLDZCQUE4QixTQUFRLHdCQUFlO0lBQ3RELEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsa0JBQWtCLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFakgsTUFBTSxvQkFBb0IsR0FBd0M7WUFDaEUsa0JBQWtCO1lBQ2xCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNO1NBQ3hDLENBQUM7UUFFRixJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1FBQ25DLE1BQU0sNEJBQTRCLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFDL0YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDRCQUE0QixFQUFFLENBQUMsQ0FBQztRQUUzQyxJQUFJLENBQUMsNEJBQTRCLENBQUMsY0FBYyxFQUFFO1lBQ2hELE1BQU0sSUFBSSxLQUFLLENBQUMsdUNBQXVDLENBQUMsQ0FBQztTQUMxRDtRQUVELE9BQU87WUFDTCxrQkFBa0IsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsa0JBQWtCO1lBQ2xGLElBQUksRUFBRTtnQkFDSixpQkFBaUIsRUFBRSw0QkFBNEIsQ0FBQyxjQUFjLENBQUMsaUJBQWlCO2FBQ2pGO1NBQ0YsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtZQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLCtDQUErQyxDQUFDLENB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QUNwRSxJQUFJLENBQUMsR0FBRyxDQUFDLGdHQUFnRyxDQUFDLENBQUM7Z0JBQzNHLE9BQU8sV0FBVyxDQUFDO2FBQ3BCO1lBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLDJCQUEyQixFQUFFLENBQUMsQ0FBQztZQUMxQyxNQUFNLDJCQUEyQixDQUFDO1NBQ25DO0tBQ0Y7Q0FDRjtBQWpIRCxzRUFpSEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhd3MgZnJvbSAnYXdzLXNkayc7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9OQU1FX0xFTiA9IDYzO1xuXG5leHBvcnQgY2xhc3MgRmFyZ2F0ZVByb2ZpbGVSZXNvdXJjZUhhbmRsZXIgZXh0ZW5kcyBSZXNvdXJjZUhhbmRsZXIge1xuICBwcm90ZWN0ZWQgYXN5bmMgb25DcmVhdGUoKSB7XG4gICAgY29uc3QgZmFyZ2F0ZVByb2ZpbGVOYW1lID0gdGhpcy5ldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuQ29uZmlnLmZhcmdhdGVQcm9maWxlTmFtZSA/PyB0aGlzLmdlbmVyYXRlUHJvZmlsZU5hbWUoKTtcblxuICAgIGNvbnN0IGNyZWF0ZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkNyZWF0ZUZhcmdhdGVQcm9maWxlUmVxdWVzdCA9IHtcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZSxcbiAgICAgIC4uLnRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZyxcbiAgICB9O1xuXG4gICAgdGhpcy5sb2coeyBjcmVhdGVGYXJnYXRlUHJvZmlsZSB9KTtcbiAgICBjb25zdCBjcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuY3JlYXRlRmFyZ2F0ZVByb2ZpbGUoY3JlYXRlRmFyZ2F0ZVByb2ZpbGUpO1xuICAgIHRoaXMubG9nKHsgY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIENyZWF0ZUZhcmdhdGVQcm9maWxlIHJlc3BvbnNlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogY3JlYXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZS5mYXJnYXRlUHJvZmlsZU5hbWUsXG4gICAgICBEYXRhOiB7XG4gICAgICAgIGZhcmdhdGVQcm9maWxlQXJuOiBjcmVhdGVGYXJnYXRlUHJvZmlsZVJlc3BvbnNlLmZhcmdhdGVQcm9maWxlLmZhcmdhdGVQcm9maWxlQXJuLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIG9uRGVsZXRlKCkge1xuICAgIGlmICghdGhpcy5waHlzaWNhbFJlc291cmNlSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGRlbGV0ZSBhIHByb2ZpbGUgd2l0aG91dCBhIHBoeXNpY2FsIGlkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGVsZXRlRmFyZ2F0ZVByb2ZpbGU6IGF3cy5FS1MuRGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgICAgY2x1c3Rlck5hbWU6IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5jbHVzdGVyTmFtZSxcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZTogdGhpcy5waHlzaWNhbFJlc291cmNlSWQsXG4gICAgfTtcblxuICAgIHRoaXMubG9nKHsgZGVsZXRlRmFyZ2F0ZVByb2ZpbGUgfSk7XG4gICAgY29uc3QgZGVsZXRlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmRlbGV0ZUZhcmdhdGVQcm9maWxlKGRlbGV0ZUZhcmdhdGVQcm9maWxlKTtcbiAgICB0aGlzLmxvZyh7IGRlbGV0ZUZhcmdhdGVQcm9maWxlUmVzcG9uc2UgfSk7XG5cbiAgICByZXR1cm47XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgLy8gYWxsIHVwZGF0ZXMgcmVxdWlyZSBhIHJlcGxhY2VtZW50LiBhcyBsb25nIGFzIG5hbWUgaXMgZ2VuZXJhdGVkLCB3ZSBhcmVcbiAgICAvLyBnb29kLiBpZiBuYW1lIGlzIGV4cGxpY2l0LCB1cGRhdGUgd2lsbCBmYWlsLCB3aGljaCBpcyBjb21tb24gd2hlbiB0cnlpbmdcbiAgICAvLyB0byByZXBsYWNlIGNmbiByZXNvdXJjZXMgd2l0aCBleHBsaWNpdCBwaHlzaWNhbCBuYW1lc1xuICAgIHJldHVybiB0aGlzLm9uQ3JlYXRlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1VwZGF0ZUNvbXBsZXRlKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNVcGRhdGVDb21wbGV0ZSgpIHtcbiAgICBjb25zdCBzdGF0dXMgPSBhd2FpdCB0aGlzLnF1ZXJ5U3RhdHVzKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIElzQ29tcGxldGU6IHN0YXR1cyA9PT0gJ0FDVElWRScsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMucXVlcnlTdGF0dXMoKTtcbiAgICByZXR1cm4ge1xuICAgICAgSXNDb21wbGV0ZTogc3RhdHVzID09PSAnTk9UX0ZPVU5EJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlcyBhIGZhcmdhdGUgcHJvZmlsZSBuYW1lLlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVByb2ZpbGVOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9OQU1FX0xFTiAtIHN1ZmZpeC5sZW5ndGggLSAxO1xuICAgIGNvbnN0IHByZWZpeCA9IHRoaXMubG9naWNhbFJlc291cmNlSWQuc2xpY2UoMCwgb2Zmc2V0ID4gMCA/IG9mZnNldCA6IDApO1xuICAgIHJldHVybiBgJHtwcmVmaXh9LSR7c3VmZml4fWA7XG4gIH1cblxuICAvKipcbiAgICogUXVlcmllcyB0aGUgRmFyZ2F0ZSBwcm9maWxlJ3MgY3VycmVudCBzdGF0dXMgYW5kIHJldHVybnMgdGhlIHN0YXR1cyBvclxuICAgKiBOT1RfRk9VTkQgaWYgdGhlIHByb2ZpbGUgZG9lc24ndCBleGlzdCAoaS5lLiBpdCBoYXMgYmVlbiBkZWxldGVkKS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcXVlcnlTdGF0dXMoKTogUHJvbWlzZTxhd3MuRUtTLkZhcmdhdGVQcm9maWxlU3RhdHVzIHwgJ05PVF9GT1VORCcgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIXRoaXMucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBkZXRlcm1pbmUgc3RhdHVzIGZvciBmYXJnYXRlIHByb2ZpbGUgd2l0aG91dCBhIHJlc291cmNlIG5hbWUnKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZXNjcmliZUZhcmdhdGVQcm9maWxlOiBhd3MuRUtTLkRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXF1ZXN0ID0ge1xuICAgICAgY2x1c3Rlck5hbWU6IHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkNvbmZpZy5jbHVzdGVyTmFtZSxcbiAgICAgIGZhcmdhdGVQcm9maWxlTmFtZTogdGhpcy5waHlzaWNhbFJlc291cmNlSWQsXG4gICAgfTtcblxuICAgIHRyeSB7XG5cbiAgICAgIHRoaXMubG9nKHsgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZSB9KTtcbiAgICAgIGNvbnN0IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGUoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZSk7XG4gICAgICB0aGlzLmxvZyh7IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZSB9KTtcbiAgICAgIGNvbnN0IHN0YXR1cyA9IGRlc2NyaWJlRmFyZ2F0ZVByb2ZpbGVSZXNwb25zZS5mYXJnYXRlUHJvZmlsZT8uc3RhdHVzO1xuXG4gICAgICBpZiAoc3RhdHVzID09PSAnQ1JFQVRFX0ZBSUxFRCcgfHwgc3RhdHVzID09PSAnREVMRVRFX0ZBSUxFRCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHN0YXR1cyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzdGF0dXM7XG4gICAgfSBjYXRjaCAoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yKSB7XG4gICAgICBpZiAoZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICB0aGlzLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgcHJvZmlsZSBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4gJ05PVF9GT1VORCc7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubG9nKHsgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yIH0pO1xuICAgICAgdGhyb3cgZGVzY3JpYmVGYXJnYXRlUHJvZmlsZUVycm9yO1xuICAgIH1cbiAgfVxufVxuIl19 \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts new file mode 100644 index 0000000000000..b708690efd6d9 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/fargate.ts @@ -0,0 +1,119 @@ +import * as aws from 'aws-sdk'; // eslint-disable-line import/no-extraneous-dependencies +import { ResourceHandler } from './common'; + +const MAX_NAME_LEN = 63; + +export class FargateProfileResourceHandler extends ResourceHandler { + protected async onCreate() { + const fargateProfileName = this.event.ResourceProperties.Config.fargateProfileName ?? this.generateProfileName(); + + const createFargateProfile: aws.EKS.CreateFargateProfileRequest = { + fargateProfileName, + ...this.event.ResourceProperties.Config, + }; + + this.log({ createFargateProfile }); + const createFargateProfileResponse = await this.eks.createFargateProfile(createFargateProfile); + this.log({ createFargateProfileResponse }); + + if (!createFargateProfileResponse.fargateProfile) { + throw new Error('invalid CreateFargateProfile response'); + } + + return { + PhysicalResourceId: createFargateProfileResponse.fargateProfile.fargateProfileName, + Data: { + fargateProfileArn: createFargateProfileResponse.fargateProfile.fargateProfileArn, + }, + }; + } + + protected async onDelete() { + if (!this.physicalResourceId) { + throw new Error('Cannot delete a profile without a physical id'); + } + + const deleteFargateProfile: aws.EKS.DeleteFargateProfileRequest = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + + this.log({ deleteFargateProfile }); + const deleteFargateProfileResponse = await this.eks.deleteFargateProfile(deleteFargateProfile); + this.log({ deleteFargateProfileResponse }); + + return; + } + + protected async onUpdate() { + // all updates require a replacement. as long as name is generated, we are + // good. if name is explicit, update will fail, which is common when trying + // to replace cfn resources with explicit physical names + return this.onCreate(); + } + + protected async isCreateComplete() { + return this.isUpdateComplete(); + } + + protected async isUpdateComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'ACTIVE', + }; + } + + protected async isDeleteComplete() { + const status = await this.queryStatus(); + return { + IsComplete: status === 'NOT_FOUND', + }; + } + + /** + * Generates a fargate profile name. + */ + private generateProfileName() { + const suffix = this.requestId.replace(/-/g, ''); // 32 chars + const offset = MAX_NAME_LEN - suffix.length - 1; + const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); + return `${prefix}-${suffix}`; + } + + /** + * Queries the Fargate profile's current status and returns the status or + * NOT_FOUND if the profile doesn't exist (i.e. it has been deleted). + */ + private async queryStatus(): Promise { + if (!this.physicalResourceId) { + throw new Error('Unable to determine status for fargate profile without a resource name'); + } + + const describeFargateProfile: aws.EKS.DescribeFargateProfileRequest = { + clusterName: this.event.ResourceProperties.Config.clusterName, + fargateProfileName: this.physicalResourceId, + }; + + try { + + this.log({ describeFargateProfile }); + const describeFargateProfileResponse = await this.eks.describeFargateProfile(describeFargateProfile); + this.log({ describeFargateProfileResponse }); + const status = describeFargateProfileResponse.fargateProfile?.status; + + if (status === 'CREATE_FAILED' || status === 'DELETE_FAILED') { + throw new Error(status); + } + + return status; + } catch (describeFargateProfileError) { + if (describeFargateProfileError.code === 'ResourceNotFoundException') { + this.log('received ResourceNotFoundException, this means the profile has been deleted (or never existed)'); + return 'NOT_FOUND'; + } + + this.log({ describeFargateProfileError }); + throw describeFargateProfileError; + } + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.d.ts rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.d.ts diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/index.js rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.js diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts new file mode 100644 index 0000000000000..f4db036cc6e48 --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee/index.ts @@ -0,0 +1,67 @@ +/* eslint-disable no-console */ +// eslint-disable-next-line import/no-extraneous-dependencies +import { IsCompleteResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; +// eslint-disable-next-line import/no-extraneous-dependencies +import * as aws from 'aws-sdk'; +import { ClusterResourceHandler } from './cluster'; +import { EksClient } from './common'; +import * as consts from './consts'; +import { FargateProfileResourceHandler } from './fargate'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-extraneous-dependencies +const ProxyAgent = require('proxy-agent'); + +aws.config.logger = console; +aws.config.update({ + httpOptions: { agent: new ProxyAgent() }, +}); + +let eks: aws.EKS | undefined; + +const defaultEksClient: EksClient = { + createCluster: req => getEksClient().createCluster(req).promise(), + deleteCluster: req => getEksClient().deleteCluster(req).promise(), + describeCluster: req => getEksClient().describeCluster(req).promise(), + describeUpdate: req => getEksClient().describeUpdate(req).promise(), + updateClusterConfig: req => getEksClient().updateClusterConfig(req).promise(), + updateClusterVersion: req => getEksClient().updateClusterVersion(req).promise(), + createFargateProfile: req => getEksClient().createFargateProfile(req).promise(), + deleteFargateProfile: req => getEksClient().deleteFargateProfile(req).promise(), + describeFargateProfile: req => getEksClient().describeFargateProfile(req).promise(), + configureAssumeRole: req => { + console.log(JSON.stringify({ assumeRole: req }, undefined, 2)); + const creds = new aws.ChainableTemporaryCredentials({ + params: req, + stsConfig: { stsRegionalEndpoints: 'regional' }, + }); + + eks = new aws.EKS({ credentials: creds }); + }, +}; + +function getEksClient() { + if (!eks) { + throw new Error('EKS client not initialized (call "configureAssumeRole")'); + } + + return eks; +} + +export async function onEvent(event: AWSLambda.CloudFormationCustomResourceEvent) { + const provider = createResourceHandler(event); + return provider.onEvent(); +} + +export async function isComplete(event: AWSLambda.CloudFormationCustomResourceEvent): Promise { + const provider = createResourceHandler(event); + return provider.isComplete(); +} + +function createResourceHandler(event: AWSLambda.CloudFormationCustomResourceEvent) { + switch (event.ResourceType) { + case consts.CLUSTER_RESOURCE_TYPE: return new ClusterResourceHandler(defaultEksClient, event); + case consts.FARGATE_PROFILE_RESOURCE_TYPE: return new FargateProfileResourceHandler(defaultEksClient, event); + default: + throw new Error(`Unsupported resource type "${event.ResourceType}`); + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip index 298edd40a09fc..f62fe1e5a06d6 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.5d8d1d0aacea23824c62f362e1e3c14b7dd14a31c71b53bfae4d14a6373c5510.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js deleted file mode 100644 index 1d08e9d7b865b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.js +++ /dev/null @@ -1,273 +0,0 @@ -"use strict"; -/* eslint-disable no-console */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.ClusterResourceHandler = void 0; -const common_1 = require("./common"); -const MAX_CLUSTER_NAME_LEN = 100; -class ClusterResourceHandler extends common_1.ResourceHandler { - constructor(eks, event) { - super(eks, event); - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - return this.physicalResourceId; - } - // ------ - // CREATE - // ------ - async onCreate() { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - const clusterName = this.newProps.name || this.generateClusterName(); - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - return { - PhysicalResourceId: resp.cluster.name, - }; - } - async isCreateComplete() { - return this.isActive(); - } - // ------ - // DELETE - // ------ - async onDelete() { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } - catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } - else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - async isDeleteComplete() { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } - catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - console.log('describeCluster error:', e); - throw e; - } - return { - IsComplete: false, - }; - } - // ------ - // UPDATE - // ------ - async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - return this.onCreate(); - } - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - return this.updateClusterVersion(this.newProps.version); - } - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - if (updates.updateLogging || updates.updateAccess) { - const config = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - } - ; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - return { EksUpdateId: updateResponse.update?.id }; - } - // no updates - return; - } - async isUpdateComplete() { - console.log('isUpdateComplete'); - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - return this.isActive(); - } - async updateClusterVersion(newVersion) { - console.log(`updating cluster version to ${newVersion}`); - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - async isActive() { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } - else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } - else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - async isEksUpdateComplete(eksUpdateId) { - this.log({ isEksUpdateComplete: eksUpdateId }); - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - this.log({ describeUpdateResponse }); - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} -exports.ClusterResourceHandler = ClusterResourceHandler; -function parseProps(props) { - const parsed = props?.Config ?? {}; - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - return parsed; -} -function analyzeUpdate(oldProps, newProps) { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} -function setsEqual(first, second) { - return first.size === second.size && [...first].every((e) => second.has(e)); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtCQUErQjs7O0FBTS9CLHFDQUFxRTtBQUVyRSxNQUFNLG9CQUFvQixHQUFHLEdBQUcsQ0FBQztBQUVqQyxNQUFhLHNCQUF1QixTQUFRLHdCQUFlO0lBWXpELFlBQVksR0FBYyxFQUFFLEtBQW9CO1FBQzlDLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQy9GO0lBaEJELElBQVcsV0FBVztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsNERBQTRELENBQUMsQ0FBQztTQUMvRTtRQUVELE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0tBQ2hDO0lBWUQsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBRUMsS0FBSyxDQUFDLFFBQVE7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQ0FBMEMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFO1lBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztTQUMxQztRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRXJFLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixJQUFJLEVBQUUsV0FBVztTQUNsQixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVDQUF1QyxXQUFXLHNEQUFzRCxDQUFDLENBQUM7U0FDM0g7UUFFRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJO1NBQ3RDLENBQUM7S0FDSDtJQUVTLEtBQUssQ0FBQyxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDeEI7SUFFRCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFFQyxLQUFLLENBQUMsUUFBUTtRQUN0QixPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUM5RCxJQUFJO1lBQ0YsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztTQUMxRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLDJCQUEyQixFQUFFO2dCQUMxQyxNQUFNLENBQUMsQ0FBQzthQUNUO2lCQUFNO2dCQUNMLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLENBQUMsV0FBVyxvQ0FBb0MsQ0FBQyxDQUFDO2FBQzlFO1NBQ0Y7UUFDRCxPQUFPO1lBQ0wsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFdBQVc7U0FDckMsQ0FBQztLQUNIO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsV0FBVyxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXZGLElBQUk7WUFDRixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDOUU7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSywyQkFBMkIsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnR0FBZ0csQ0FBQyxDQUFDO2dCQUM5RyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO2FBQzdCO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsQ0FBQztTQUNUO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxLQUFLO1NBQ2xCLENBQUM7S0FDSDtJQUVELFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUVDLEtBQUssQ0FBQyxRQUFRO1FBQ3RCLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM1RCxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsZ0RBQWdEO1FBQ2hELElBQUksT0FBTyxDQUFDLGdCQUFnQixFQUFFO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztTQUNuRTtRQUVELDRFQUE0RTtRQUM1RSwyRUFBMkU7UUFDM0UsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFFcEUsbUVBQW1FO1lBQ25FLDBFQUEwRTtZQUMxRSxtRUFBbUU7WUFDbkUsb0VBQW9FO1lBQ3BFLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUU7Z0JBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSx3R0FBd0csQ0FBQyxDQUFDO2FBQ3hLO1lBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDeEI7UUFFRCw0REFBNEQ7UUFDNUQsSUFBSSxPQUFPLENBQUMsYUFBYSxFQUFFO1lBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtnQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO2FBQzdHO1lBRUQsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUN6RDtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELENBQUMsQ0FBQztTQUN0RTtRQUVELElBQUksT0FBTyxDQUFDLGFBQWEsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sTUFBTSxHQUF1QztnQkFDakQsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXO2FBQ3ZCLENBQUM7WUFDRixJQUFJLE9BQU8sQ0FBQyxhQUFhLEVBQUU7Z0JBQ3pCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7YUFDeEM7WUFBQSxDQUFDO1lBQ0YsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFO2dCQUN4Qiw4RkFBOEY7Z0JBQzlGLHFHQUFxRztnQkFDckcsaUVBQWlFO2dCQUNqRSxNQUFNLENBQUMsa0JBQWtCLEdBQUc7b0JBQzFCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMscUJBQXFCO29CQUM3RSxvQkFBb0IsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQjtvQkFDM0UsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxpQkFBaUI7aUJBQ3RFLENBQUM7YUFDSDtZQUNELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUVsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7U0FDbkQ7UUFFRCxhQUFhO1FBQ2IsT0FBTztLQUNSO0lBRVMsS0FBSyxDQUFDLGdCQUFnQjtRQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFFaEMsb0VBQW9FO1FBQ3BFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDMUIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNiLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7YUFDOUI7WUFFRCx3RUFBd0U7WUFDeEUsMEVBQTBFO1lBQzFFLHFFQUFxRTtTQUN0RTtRQUVELE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ3hCO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUFDLFVBQWtCO1FBQ25ELE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFFekQsNEVBQTRFO1FBQzVFLHdCQUF3QjtRQUN4QixNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7UUFDckYsSUFBSSxPQUFPLEVBQUUsT0FBTyxLQUFLLFVBQVUsRUFBRTtZQUNuQyxPQUFPLENBQUMsR0FBRyxDQUFDLDhCQUE4QixPQUFPLENBQUMsT0FBTywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3RGLE9BQU87U0FDUjtRQUVELE1BQU0sY0FBYyxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQzVHLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQztLQUNuRDtJQUVPLEtBQUssQ0FBQyxRQUFRO1FBQ3BCLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0NBQXNDLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sQ0FBQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUU3Qiw0RUFBNEU7UUFDNUUseUVBQXlFO1FBQ3pFLHNEQUFzRDtRQUN0RCxJQUFJLE9BQU8sRUFBRSxNQUFNLEtBQUssUUFBUSxFQUFFO1lBQ2hDLDZFQUE2RTtZQUM3RSxpQkFBaUI7WUFDakIsTUFBTSxJQUFJLEtBQUssQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO1NBQ2xEO2FBQU0sSUFBSSxPQUFPLEVBQUUsTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUN2QyxPQUFPO2dCQUNMLFVBQVUsRUFBRSxLQUFLO2FBQ2xCLENBQUM7U0FDSDthQUFNO1lBQ0wsT0FBTztnQkFDTCxVQUFVLEVBQUUsSUFBSTtnQkFDaEIsSUFBSSxFQUFFO29CQUNKLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO29CQUMxQixHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUc7b0JBRWhCLG9FQUFvRTtvQkFDcEUsOERBQThEO29CQUM5RCxrRUFBa0U7b0JBQ2xFLGFBQWE7b0JBRWIsd0JBQXdCLEVBQUUsT0FBTyxDQUFDLG9CQUFvQixFQUFFLElBQUksSUFBSSxFQUFFO29CQUNsRSxzQkFBc0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCLEVBQUUsc0JBQXNCLElBQUksRUFBRTtvQkFDaEYsc0JBQXNCLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxJQUFJLEVBQUU7b0JBQzVELG1CQUFtQixFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRTtvQkFFdkUsNEdBQTRHO29CQUM1Ryw4SEFBOEg7b0JBQzlILHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLEVBQUU7aUJBQ2xGO2FBQ0YsQ0FBQztTQUNIO0tBQ0Y7SUFFTyxLQUFLLENBQUMsbUJBQW1CLENBQUMsV0FBbUI7UUFDbkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFFL0MsTUFBTSxzQkFBc0IsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO1lBQzNELElBQUksRUFBRSxJQUFJLENBQUMsV0FBVztZQUN0QixRQUFRLEVBQUUsV0FBVztTQUN0QixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDO1FBRXJDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUU7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsV0FBVyxHQUFHLENBQUMsQ0FBQztTQUN2RTtRQUVELFFBQVEsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUM1QyxLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxLQUFLLENBQUM7WUFDZixLQUFLLFlBQVk7Z0JBQ2YsT0FBTyxJQUFJLENBQUM7WUFDZCxLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssV0FBVztnQkFDZCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixXQUFXLHlCQUF5QixJQUFJLENBQUMsU0FBUyxDQUFDLHNCQUFzQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEk7Z0JBQ0UsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDOUc7S0FDRjtJQUVPLG1CQUFtQjtRQUN6QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXO1FBQzVELE1BQU0sTUFBTSxHQUFHLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsT0FBTyxHQUFHLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztLQUM5QjtDQUNGO0FBM1FELHdEQTJRQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQVU7SUFFNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFbkMsMEhBQTBIO0lBQzFILDhIQUE4SDtJQUU5SCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUscUJBQXFCLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDMUUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxxQkFBcUIsS0FBSyxNQUFNLENBQUM7S0FDOUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsa0JBQWtCLEVBQUUsb0JBQW9CLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDekUsTUFBTSxDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsS0FBSyxNQUFNLENBQUM7S0FDNUc7SUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7UUFDbkUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxNQUFNLENBQUM7S0FDaEc7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUVoQixDQUFDO0FBYUQsU0FBUyxhQUFhLENBQUMsUUFBK0MsRUFBRSxRQUFzQztJQUM1RyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDckQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBRXJELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxFQUFFLENBQUM7SUFDdEQsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLGtCQUFrQixJQUFJLEVBQUUsQ0FBQztJQUV0RCxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLG9CQUFvQixHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUMxRSxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsZ0JBQWdCLElBQUksRUFBRSxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsSUFBSSxFQUFFLENBQUM7SUFFL0MsT0FBTztRQUNMLFdBQVcsRUFBRSxRQUFRLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQyxJQUFJO1FBQzVDLFVBQVUsRUFDUixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUM7WUFDL0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvRixZQUFZLEVBQ1YsV0FBVyxDQUFDLHFCQUFxQixLQUFLLFdBQVcsQ0FBQyxxQkFBcUI7WUFDdkUsV0FBVyxDQUFDLG9CQUFvQixLQUFLLFdBQVcsQ0FBQyxvQkFBb0I7WUFDckUsQ0FBQyxTQUFTLENBQUMsb0JBQW9CLEVBQUUsb0JBQW9CLENBQUM7UUFDeEQsV0FBVyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDbEQsYUFBYSxFQUFFLFFBQVEsQ0FBQyxPQUFPLEtBQUssUUFBUSxDQUFDLE9BQU87UUFDcEQsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztRQUNuRSxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO0tBQ3JGLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBa0IsRUFBRSxNQUFtQjtJQUN4RCxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDdEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLWNvbnNvbGUgKi9cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgSXNDb21wbGV0ZVJlc3BvbnNlLCBPbkV2ZW50UmVzcG9uc2UgfSBmcm9tICdAYXdzLWNkay9jdXN0b20tcmVzb3VyY2VzL2xpYi9wcm92aWRlci1mcmFtZXdvcmsvdHlwZXMnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgYXdzIGZyb20gJ2F3cy1zZGsnO1xuaW1wb3J0IHsgRWtzQ2xpZW50LCBSZXNvdXJjZUV2ZW50LCBSZXNvdXJjZUhhbmRsZXIgfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IE1BWF9DTFVTVEVSX05BTUVfTEVOID0gMTAwO1xuXG5leHBvcnQgY2xhc3MgQ2x1c3RlclJlc291cmNlSGFuZGxlciBleHRlbmRzIFJlc291cmNlSGFuZGxlciB7XG4gIHB1YmxpYyBnZXQgY2x1c3Rlck5hbWUoKSB7XG4gICAgaWYgKCF0aGlzLnBoeXNpY2FsUmVzb3VyY2VJZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZGV0ZXJtaW5lIGNsdXN0ZXIgbmFtZSB3aXRob3V0IHBoeXNpY2FsIHJlc291cmNlIElEJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxSZXNvdXJjZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBuZXdQcm9wczogYXdzLkVLUy5DcmVhdGVDbHVzdGVyUmVxdWVzdDtcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PjtcblxuICBjb25zdHJ1Y3Rvcihla3M6IEVrc0NsaWVudCwgZXZlbnQ6IFJlc291cmNlRXZlbnQpIHtcbiAgICBzdXBlcihla3MsIGV2ZW50KTtcblxuICAgIHRoaXMubmV3UHJvcHMgPSBwYXJzZVByb3BzKHRoaXMuZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzKTtcbiAgICB0aGlzLm9sZFByb3BzID0gZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnID8gcGFyc2VQcm9wcyhldmVudC5PbGRSZXNvdXJjZVByb3BlcnRpZXMpIDoge307XG4gIH1cblxuICAvLyAtLS0tLS1cbiAgLy8gQ1JFQVRFXG4gIC8vIC0tLS0tLVxuXG4gIHByb3RlY3RlZCBhc3luYyBvbkNyZWF0ZSgpOiBQcm9taXNlPE9uRXZlbnRSZXNwb25zZT4ge1xuICAgIGNvbnNvbGUubG9nKCdvbkNyZWF0ZTogY3JlYXRpbmcgY2x1c3RlciB3aXRoIG9wdGlvbnM6JywgSlNPTi5zdHJpbmdpZnkodGhpcy5uZXdQcm9wcywgdW5kZWZpbmVkLCAyKSk7XG4gICAgaWYgKCF0aGlzLm5ld1Byb3BzLnJvbGVBcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignXCJyb2xlQXJuXCIgaXMgcmVxdWlyZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyTmFtZSA9IHRoaXMubmV3UHJvcHMubmFtZSB8fCB0aGlzLmdlbmVyYXRlQ2x1c3Rlck5hbWUoKTtcblxuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmVrcy5jcmVhdGVDbHVzdGVyKHtcbiAgICAgIC4uLnRoaXMubmV3UHJvcHMsXG4gICAgICBuYW1lOiBjbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcC5jbHVzdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBjbHVzdGVyICR7Y2x1c3Rlck5hbWV9OiBDcmVhdGVDbHVzdGVyIHJldHVybmVkIHdpdGhvdXQgY2x1c3RlciBpbmZvcm1hdGlvbmApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHJlc3AuY2x1c3Rlci5uYW1lLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgaXNDcmVhdGVDb21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIERFTEVURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25EZWxldGUoKTogUHJvbWlzZTxPbkV2ZW50UmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZyhgb25EZWxldGU6IGRlbGV0aW5nIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfWApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVrcy5kZWxldGVDbHVzdGVyKHsgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZS5jb2RlICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyICR7dGhpcy5jbHVzdGVyTmFtZX0gbm90IGZvdW5kLCBpZGVtcG90ZW50bHkgc3VjY2VlZGVkYCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgfTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBpc0RlbGV0ZUNvbXBsZXRlKCk6IFByb21pc2U8SXNDb21wbGV0ZVJlc3BvbnNlPiB7XG4gICAgY29uc29sZS5sb2coYGlzRGVsZXRlQ29tcGxldGU6IHdhaXRpbmcgZm9yIGNsdXN0ZXIgJHt0aGlzLmNsdXN0ZXJOYW1lfSB0byBiZSBkZWxldGVkYCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgICBjb25zb2xlLmxvZygnZGVzY3JpYmVDbHVzdGVyIHJldHVybmVkOicsIEpTT04uc3RyaW5naWZ5KHJlc3AsIHVuZGVmaW5lZCwgMikpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmIChlLmNvZGUgPT09ICdSZXNvdXJjZU5vdEZvdW5kRXhjZXB0aW9uJykge1xuICAgICAgICBjb25zb2xlLmxvZygncmVjZWl2ZWQgUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbiwgdGhpcyBtZWFucyB0aGUgY2x1c3RlciBoYXMgYmVlbiBkZWxldGVkIChvciBuZXZlciBleGlzdGVkKScpO1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiB0cnVlIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnNvbGUubG9nKCdkZXNjcmliZUNsdXN0ZXIgZXJyb3I6JywgZSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJc0NvbXBsZXRlOiBmYWxzZSxcbiAgICB9O1xuICB9XG5cbiAgLy8gLS0tLS0tXG4gIC8vIFVQREFURVxuICAvLyAtLS0tLS1cblxuICBwcm90ZWN0ZWQgYXN5bmMgb25VcGRhdGUoKSB7XG4gICAgY29uc3QgdXBkYXRlcyA9IGFuYWx5emVVcGRhdGUodGhpcy5vbGRQcm9wcywgdGhpcy5uZXdQcm9wcyk7XG4gICAgY29uc29sZS5sb2coJ29uVXBkYXRlOicsIEpTT04uc3RyaW5naWZ5KHsgdXBkYXRlcyB9LCB1bmRlZmluZWQsIDIpKTtcblxuICAgIC8vIHVwZGF0ZXMgdG8gZW5jcnlwdGlvbiBjb25maWcgaXMgbm90IHN1cHBvcnRlZFxuICAgIGlmICh1cGRhdGVzLnVwZGF0ZUVuY3J5cHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHVwZGF0ZSBjbHVzdGVyIGVuY3J5cHRpb24gY29uZmlndXJhdGlvbicpO1xuICAgIH1cblxuICAgIC8vIGlmIHRoZXJlIGlzIGFuIHVwZGF0ZSB0aGF0IHJlcXVpcmVzIHJlcGxhY2VtZW50LCBnbyBhaGVhZCBhbmQganVzdCBjcmVhdGVcbiAgICAvLyBhIG5ldyBjbHVzdGVyIHdpdGggdGhlIG5ldyBjb25maWcuIFRoZSBvbGQgY2x1c3RlciB3aWxsIGF1dG9tYXRpY2FsbHkgYmVcbiAgICAvLyBkZWxldGVkIGJ5IGNsb3VkZm9ybWF0aW9uIHVwb24gc3VjY2Vzcy5cbiAgICBpZiAodXBkYXRlcy5yZXBsYWNlTmFtZSB8fCB1cGRhdGVzLnJlcGxhY2VSb2xlIHx8IHVwZGF0ZXMucmVwbGFjZVZwYykge1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgcmVwbGFjaW5nIHRoaXMgY2x1c3RlciBhbmQgdGhlIGNsdXN0ZXIgaGFzIGFuIGV4cGxpY2l0XG4gICAgICAvLyBwaHlzaWNhbCBuYW1lLCB0aGUgY3JlYXRpb24gb2YgdGhlIG5ldyBjbHVzdGVyIHdpbGwgZmFpbCB3aXRoIFwidGhlcmUgaXNcbiAgICAgIC8vIGFscmVhZHkgYSBjbHVzdGVyIHdpdGggdGhhdCBuYW1lXCIuIHRoaXMgaXMgYSBjb21tb24gYmVoYXZpb3IgZm9yXG4gICAgICAvLyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZXMgdGhhdCBzdXBwb3J0IHNwZWNpZnlpbmcgYSBwaHlzaWNhbCBuYW1lLlxuICAgICAgaWYgKHRoaXMub2xkUHJvcHMubmFtZSA9PT0gdGhpcy5uZXdQcm9wcy5uYW1lICYmIHRoaXMub2xkUHJvcHMubmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXBsYWNlIGNsdXN0ZXIgXCIke3RoaXMub2xkUHJvcHMubmFtZX1cIiBzaW5jZSBpdCBoYXMgYW4gZXhwbGljaXQgcGh5c2ljYWwgbmFtZS4gRWl0aGVyIHJlbmFtZSB0aGUgY2x1c3RlciBvciByZW1vdmUgdGhlIFwibmFtZVwiIGNvbmZpZ3VyYXRpb25gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMub25DcmVhdGUoKTtcbiAgICB9XG5cbiAgICAvLyBpZiBhIHZlcnNpb24gdXBkYXRlIGlzIHJlcXVpcmVkLCBpc3N1ZSB0aGUgdmVyc2lvbiB1cGRhdGVcbiAgICBpZiAodXBkYXRlcy51cGRhdGVWZXJzaW9uKSB7XG4gICAgICBpZiAoIXRoaXMubmV3UHJvcHMudmVyc2lvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZW1vdmUgY2x1c3RlciB2ZXJzaW9uIGNvbmZpZ3VyYXRpb24uIEN1cnJlbnQgdmVyc2lvbiBpcyAke3RoaXMub2xkUHJvcHMudmVyc2lvbn1gKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMudXBkYXRlQ2x1c3RlclZlcnNpb24odGhpcy5uZXdQcm9wcy52ZXJzaW9uKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nICYmIHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCB1cGRhdGUgbG9nZ2luZyBhbmQgYWNjZXNzIGF0IHRoZSBzYW1lIHRpbWUnKTtcbiAgICB9XG5cbiAgICBpZiAodXBkYXRlcy51cGRhdGVMb2dnaW5nIHx8IHVwZGF0ZXMudXBkYXRlQWNjZXNzKSB7XG4gICAgICBjb25zdCBjb25maWc6IGF3cy5FS1MuVXBkYXRlQ2x1c3RlckNvbmZpZ1JlcXVlc3QgPSB7XG4gICAgICAgIG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsXG4gICAgICB9O1xuICAgICAgaWYgKHVwZGF0ZXMudXBkYXRlTG9nZ2luZykge1xuICAgICAgICBjb25maWcubG9nZ2luZyA9IHRoaXMubmV3UHJvcHMubG9nZ2luZztcbiAgICAgIH07XG4gICAgICBpZiAodXBkYXRlcy51cGRhdGVBY2Nlc3MpIHtcbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIGNsdXN0ZXIgd2l0aCBzZWN1cml0eUdyb3VwSWRzIGFuZCBzdWJuZXRJZHMgKGFzIHNwZWNpZmllZCBpbiB0aGUgd2FybmluZyBoZXJlOlxuICAgICAgICAvLyBodHRwczovL2F3c2NsaS5hbWF6b25hd3MuY29tL3YyL2RvY3VtZW50YXRpb24vYXBpL2xhdGVzdC9yZWZlcmVuY2UvZWtzL3VwZGF0ZS1jbHVzdGVyLWNvbmZpZy5odG1sKVxuICAgICAgICAvLyB3aWxsIGZhaWwsIHRoZXJlZm9yZSB3ZSB0YWtlIG9ubHkgdGhlIGFjY2VzcyBmaWVsZHMgZXhwbGljaXRseVxuICAgICAgICBjb25maWcucmVzb3VyY2VzVnBjQ29uZmlnID0ge1xuICAgICAgICAgIGVuZHBvaW50UHJpdmF0ZUFjY2VzczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQcml2YXRlQWNjZXNzLFxuICAgICAgICAgIGVuZHBvaW50UHVibGljQWNjZXNzOiB0aGlzLm5ld1Byb3BzLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFB1YmxpY0FjY2VzcyxcbiAgICAgICAgICBwdWJsaWNBY2Nlc3NDaWRyczogdGhpcy5uZXdQcm9wcy5yZXNvdXJjZXNWcGNDb25maWcucHVibGljQWNjZXNzQ2lkcnMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCB1cGRhdGVSZXNwb25zZSA9IGF3YWl0IHRoaXMuZWtzLnVwZGF0ZUNsdXN0ZXJDb25maWcoY29uZmlnKTtcblxuICAgICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgICB9XG5cbiAgICAvLyBubyB1cGRhdGVzXG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGlzVXBkYXRlQ29tcGxldGUoKSB7XG4gICAgY29uc29sZS5sb2coJ2lzVXBkYXRlQ29tcGxldGUnKTtcblxuICAgIC8vIGlmIHRoaXMgaXMgYW4gRUtTIHVwZGF0ZSwgd2Ugd2lsbCBtb25pdG9yIHRoZSB1cGRhdGUgZXZlbnQgaXRzZWxmXG4gICAgaWYgKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpIHtcbiAgICAgIGNvbnN0IGNvbXBsZXRlID0gYXdhaXQgdGhpcy5pc0Vrc1VwZGF0ZUNvbXBsZXRlKHRoaXMuZXZlbnQuRWtzVXBkYXRlSWQpO1xuICAgICAgaWYgKCFjb21wbGV0ZSkge1xuICAgICAgICByZXR1cm4geyBJc0NvbXBsZXRlOiBmYWxzZSB9O1xuICAgICAgfVxuXG4gICAgICAvLyBmYWxsIHRocm91Z2g6IGlmIHRoZSB1cGRhdGUgaXMgZG9uZSwgd2Ugc2ltcGx5IGRlbGVnYXRlIHRvIGlzQWN0aXZlKClcbiAgICAgIC8vIGluIG9yZGVyIHRvIGV4dHJhY3QgYXR0cmlidXRlcyBhbmQgc3RhdGUgZnJvbSB0aGUgY2x1c3RlciBpdHNlbGYsIHdoaWNoXG4gICAgICAvLyBpcyBzdXBwb3NlZCB0byBiZSBpbiBhbiBBQ1RJVkUgc3RhdGUgYWZ0ZXIgdGhlIHVwZGF0ZSBpcyBjb21wbGV0ZS5cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDbHVzdGVyVmVyc2lvbihuZXdWZXJzaW9uOiBzdHJpbmcpIHtcbiAgICBjb25zb2xlLmxvZyhgdXBkYXRpbmcgY2x1c3RlciB2ZXJzaW9uIHRvICR7bmV3VmVyc2lvbn1gKTtcblxuICAgIC8vIHVwZGF0ZS1jbHVzdGVyLXZlcnNpb24gd2lsbCBmYWlsIGlmIHdlIHRyeSB0byB1cGRhdGUgdG8gdGhlIHNhbWUgdmVyc2lvbixcbiAgICAvLyBzbyBza2lwIGluIHRoaXMgY2FzZS5cbiAgICBjb25zdCBjbHVzdGVyID0gKGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSkpLmNsdXN0ZXI7XG4gICAgaWYgKGNsdXN0ZXI/LnZlcnNpb24gPT09IG5ld1ZlcnNpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKGBjbHVzdGVyIGFscmVhZHkgYXQgdmVyc2lvbiAke2NsdXN0ZXIudmVyc2lvbn0sIHNraXBwaW5nIHZlcnNpb24gdXBkYXRlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlUmVzcG9uc2UgPSBhd2FpdCB0aGlzLmVrcy51cGRhdGVDbHVzdGVyVmVyc2lvbih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUsIHZlcnNpb246IG5ld1ZlcnNpb24gfSk7XG4gICAgcmV0dXJuIHsgRWtzVXBkYXRlSWQ6IHVwZGF0ZVJlc3BvbnNlLnVwZGF0ZT8uaWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaXNBY3RpdmUoKTogUHJvbWlzZTxJc0NvbXBsZXRlUmVzcG9uc2U+IHtcbiAgICBjb25zb2xlLmxvZygnd2FpdGluZyBmb3IgY2x1c3RlciB0byBiZWNvbWUgQUNUSVZFJyk7XG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IHRoaXMuZWtzLmRlc2NyaWJlQ2x1c3Rlcih7IG5hbWU6IHRoaXMuY2x1c3Rlck5hbWUgfSk7XG4gICAgY29uc29sZS5sb2coJ2Rlc2NyaWJlQ2x1c3RlciByZXN1bHQ6JywgSlNPTi5zdHJpbmdpZnkocmVzcCwgdW5kZWZpbmVkLCAyKSk7XG4gICAgY29uc3QgY2x1c3RlciA9IHJlc3AuY2x1c3RlcjtcblxuICAgIC8vIGlmIGNsdXN0ZXIgaXMgdW5kZWZpbmVkIChzaG91bGRudCBoYXBwZW4pIG9yIHN0YXR1cyBpcyBub3QgQUNUSVZFLCB3ZSBhcmVcbiAgICAvLyBub3QgY29tcGxldGUuIG5vdGUgdGhhdCB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZyYW1ld29yayBmb3JiaWRzXG4gICAgLy8gcmV0dXJuaW5nIGF0dHJpYnV0ZXMgKERhdGEpIGlmIGlzQ29tcGxldGUgaXMgZmFsc2UuXG4gICAgaWYgKGNsdXN0ZXI/LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgIC8vIG5vdCB2ZXJ5IGluZm9ybWF0aXZlLCB1bmZvcnR1bmF0ZWx5IHRoZSByZXNwb25zZSBkb2Vzbid0IGNvbnRhaW4gYW55IGVycm9yXG4gICAgICAvLyBpbmZvcm1hdGlvbiA6XFxcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2x1c3RlciBpcyBpbiBhIEZBSUxFRCBzdGF0dXMnKTtcbiAgICB9IGVsc2UgaWYgKGNsdXN0ZXI/LnN0YXR1cyAhPT0gJ0FDVElWRScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIElzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgSXNDb21wbGV0ZTogdHJ1ZSxcbiAgICAgICAgRGF0YToge1xuICAgICAgICAgIE5hbWU6IGNsdXN0ZXIubmFtZSxcbiAgICAgICAgICBFbmRwb2ludDogY2x1c3Rlci5lbmRwb2ludCxcbiAgICAgICAgICBBcm46IGNsdXN0ZXIuYXJuLFxuXG4gICAgICAgICAgLy8gSU1QT1JUQU5UOiBDRk4gZXhwZWN0cyB0aGF0IGF0dHJpYnV0ZXMgd2lsbCAqYWx3YXlzKiBoYXZlIHZhbHVlcyxcbiAgICAgICAgICAvLyBzbyByZXR1cm4gYW4gZW1wdHkgc3RyaW5nIGluIGNhc2UgdGhlIHZhbHVlIGlzIG5vdCBkZWZpbmVkLlxuICAgICAgICAgIC8vIE90aGVyd2lzZSwgQ0ZOIHdpbGwgdGhyb3cgd2l0aCBgVmVuZG9yIHJlc3BvbnNlIGRvZXNuJ3QgY29udGFpblxuICAgICAgICAgIC8vIFhYWFgga2V5YC5cblxuICAgICAgICAgIENlcnRpZmljYXRlQXV0aG9yaXR5RGF0YTogY2x1c3Rlci5jZXJ0aWZpY2F0ZUF1dGhvcml0eT8uZGF0YSA/PyAnJyxcbiAgICAgICAgICBDbHVzdGVyU2VjdXJpdHlHcm91cElkOiBjbHVzdGVyLnJlc291cmNlc1ZwY0NvbmZpZz8uY2x1c3RlclNlY3VyaXR5R3JvdXBJZCA/PyAnJyxcbiAgICAgICAgICBPcGVuSWRDb25uZWN0SXNzdWVyVXJsOiBjbHVzdGVyLmlkZW50aXR5Py5vaWRjPy5pc3N1ZXIgPz8gJycsXG4gICAgICAgICAgT3BlbklkQ29ubmVjdElzc3VlcjogY2x1c3Rlci5pZGVudGl0eT8ub2lkYz8uaXNzdWVyPy5zdWJzdHJpbmcoOCkgPz8gJycsIC8vIFN0cmlwcyBvZmYgaHR0cHM6Ly8gZnJvbSB0aGUgaXNzdWVyIHVybFxuXG4gICAgICAgICAgLy8gV2UgY2FuIHNhZmVseSByZXR1cm4gdGhlIGZpcnN0IGl0ZW0gZnJvbSBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gYXJyYXksIGJlY2F1c2UgaXQgaGFzIGEgbGltaXQgb2YgMSBpdGVtXG4gICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Vrcy9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDbHVzdGVyLmh0bWwjQW1hem9uRUtTLUNyZWF0ZUNsdXN0ZXItcmVxdWVzdC1lbmNyeXB0aW9uQ29uZmlnXG4gICAgICAgICAgRW5jcnlwdGlvbkNvbmZpZ0tleUFybjogY2x1c3Rlci5lbmNyeXB0aW9uQ29uZmlnPy5zaGlmdCgpPy5wcm92aWRlcj8ua2V5QXJuID8/ICcnLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGlzRWtzVXBkYXRlQ29tcGxldGUoZWtzVXBkYXRlSWQ6IHN0cmluZykge1xuICAgIHRoaXMubG9nKHsgaXNFa3NVcGRhdGVDb21wbGV0ZTogZWtzVXBkYXRlSWQgfSk7XG5cbiAgICBjb25zdCBkZXNjcmliZVVwZGF0ZVJlc3BvbnNlID0gYXdhaXQgdGhpcy5la3MuZGVzY3JpYmVVcGRhdGUoe1xuICAgICAgbmFtZTogdGhpcy5jbHVzdGVyTmFtZSxcbiAgICAgIHVwZGF0ZUlkOiBla3NVcGRhdGVJZCxcbiAgICB9KTtcblxuICAgIHRoaXMubG9nKHsgZGVzY3JpYmVVcGRhdGVSZXNwb25zZSB9KTtcblxuICAgIGlmICghZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5hYmxlIHRvIGRlc2NyaWJlIHVwZGF0ZSB3aXRoIGlkIFwiJHtla3NVcGRhdGVJZH1cImApO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzKSB7XG4gICAgICBjYXNlICdJblByb2dyZXNzJzpcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgY2FzZSAnU3VjY2Vzc2Z1bCc6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgY2FzZSAnRmFpbGVkJzpcbiAgICAgIGNhc2UgJ0NhbmNlbGxlZCc6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY2x1c3RlciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiIGZhaWxlZCB3aXRoIGVycm9yczogJHtKU09OLnN0cmluZ2lmeShkZXNjcmliZVVwZGF0ZVJlc3BvbnNlLnVwZGF0ZS5lcnJvcnMpfWApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bmtub3duIHN0YXR1cyBcIiR7ZGVzY3JpYmVVcGRhdGVSZXNwb25zZS51cGRhdGUuc3RhdHVzfVwiIGZvciB1cGRhdGUgaWQgXCIke2Vrc1VwZGF0ZUlkfVwiYCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZUNsdXN0ZXJOYW1lKCkge1xuICAgIGNvbnN0IHN1ZmZpeCA9IHRoaXMucmVxdWVzdElkLnJlcGxhY2UoLy0vZywgJycpOyAvLyAzMiBjaGFyc1xuICAgIGNvbnN0IG9mZnNldCA9IE1BWF9DTFVTVEVSX05BTUVfTEVOIC0gc3VmZml4Lmxlbmd0aCAtIDE7XG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5sb2dpY2FsUmVzb3VyY2VJZC5zbGljZSgwLCBvZmZzZXQgPiAwID8gb2Zmc2V0IDogMCk7XG4gICAgcmV0dXJuIGAke3ByZWZpeH0tJHtzdWZmaXh9YDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVByb3BzKHByb3BzOiBhbnkpOiBhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0IHtcblxuICBjb25zdCBwYXJzZWQgPSBwcm9wcz8uQ29uZmlnID8/IHt9O1xuXG4gIC8vIHRoaXMgaXMgd2VpcmQgYnV0IHRoZXNlIGJvb2xlYW4gcHJvcGVydGllcyBhcmUgcGFzc2VkIGJ5IENGTiBhcyBhIHN0cmluZywgYW5kIHdlIG5lZWQgdGhlbSB0byBiZSBib29sZWFuaWMgZm9yIHRoZSBTREsuXG4gIC8vIE90aGVyd2lzZSBpdCBmYWlscyB3aXRoICdVbmV4cGVjdGVkIFBhcmFtZXRlcjogcGFyYW1zLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgaXMgZXhwZWN0ZWQgdG8gYmUgYSBib29sZWFuJ1xuXG4gIGlmICh0eXBlb2YgKHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWc/LmVuZHBvaW50UHJpdmF0ZUFjY2VzcykgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyA9PT0gJ3RydWUnO1xuICB9XG5cbiAgaWYgKHR5cGVvZiAocGFyc2VkLnJlc291cmNlc1ZwY0NvbmZpZz8uZW5kcG9pbnRQdWJsaWNBY2Nlc3MpID09PSAnc3RyaW5nJykge1xuICAgIHBhcnNlZC5yZXNvdXJjZXNWcGNDb25maWcuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgPSBwYXJzZWQucmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHVibGljQWNjZXNzID09PSAndHJ1ZSc7XG4gIH1cblxuICBpZiAodHlwZW9mIChwYXJzZWQubG9nZ2luZz8uY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCkgPT09ICdzdHJpbmcnKSB7XG4gICAgcGFyc2VkLmxvZ2dpbmcuY2x1c3RlckxvZ2dpbmdbMF0uZW5hYmxlZCA9IHBhcnNlZC5sb2dnaW5nLmNsdXN0ZXJMb2dnaW5nWzBdLmVuYWJsZWQgPT09ICd0cnVlJztcbiAgfVxuXG4gIHJldHVybiBwYXJzZWQ7XG5cbn1cblxuaW50ZXJmYWNlIFVwZGF0ZU1hcCB7XG4gIHJlcGxhY2VOYW1lOiBib29sZWFuOyAvLyBuYW1lXG4gIHJlcGxhY2VWcGM6IGJvb2xlYW47IC8vIHJlc291cmNlc1ZwY0NvbmZpZy5zdWJuZXRJZHMgYW5kIHNlY3VyaXR5R3JvdXBJZHNcbiAgcmVwbGFjZVJvbGU6IGJvb2xlYW47IC8vIHJvbGVBcm5cblxuICB1cGRhdGVWZXJzaW9uOiBib29sZWFuOyAvLyB2ZXJzaW9uXG4gIHVwZGF0ZUxvZ2dpbmc6IGJvb2xlYW47IC8vIGxvZ2dpbmdcbiAgdXBkYXRlRW5jcnlwdGlvbjogYm9vbGVhbjsgLy8gZW5jcnlwdGlvbiAoY2Fubm90IGJlIHVwZGF0ZWQpXG4gIHVwZGF0ZUFjY2VzczogYm9vbGVhbjsgLy8gcmVzb3VyY2VzVnBjQ29uZmlnLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyBhbmQgZW5kcG9pbnRQdWJsaWNBY2Nlc3Ncbn1cblxuZnVuY3Rpb24gYW5hbHl6ZVVwZGF0ZShvbGRQcm9wczogUGFydGlhbDxhd3MuRUtTLkNyZWF0ZUNsdXN0ZXJSZXF1ZXN0PiwgbmV3UHJvcHM6IGF3cy5FS1MuQ3JlYXRlQ2x1c3RlclJlcXVlc3QpOiBVcGRhdGVNYXAge1xuICBjb25zb2xlLmxvZygnb2xkIHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShvbGRQcm9wcykpO1xuICBjb25zb2xlLmxvZygnbmV3IHByb3BzOiAnLCBKU09OLnN0cmluZ2lmeShuZXdQcm9wcykpO1xuXG4gIGNvbnN0IG5ld1ZwY1Byb3BzID0gbmV3UHJvcHMucmVzb3VyY2VzVnBjQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRWcGNQcm9wcyA9IG9sZFByb3BzLnJlc291cmNlc1ZwY0NvbmZpZyB8fCB7fTtcblxuICBjb25zdCBvbGRQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQob2xkVnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdQdWJsaWNBY2Nlc3NDaWRycyA9IG5ldyBTZXQobmV3VnBjUHJvcHMucHVibGljQWNjZXNzQ2lkcnMgPz8gW10pO1xuICBjb25zdCBuZXdFbmMgPSBuZXdQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuICBjb25zdCBvbGRFbmMgPSBvbGRQcm9wcy5lbmNyeXB0aW9uQ29uZmlnIHx8IHt9O1xuXG4gIHJldHVybiB7XG4gICAgcmVwbGFjZU5hbWU6IG5ld1Byb3BzLm5hbWUgIT09IG9sZFByb3BzLm5hbWUsXG4gICAgcmVwbGFjZVZwYzpcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnN1Ym5ldElkcykgIT09IEpTT04uc3RyaW5naWZ5KG9sZFZwY1Byb3BzLnN1Ym5ldElkcykgfHxcbiAgICAgIEpTT04uc3RyaW5naWZ5KG5ld1ZwY1Byb3BzLnNlY3VyaXR5R3JvdXBJZHMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRWcGNQcm9wcy5zZWN1cml0eUdyb3VwSWRzKSxcbiAgICB1cGRhdGVBY2Nlc3M6XG4gICAgICBuZXdWcGNQcm9wcy5lbmRwb2ludFByaXZhdGVBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHJpdmF0ZUFjY2VzcyB8fFxuICAgICAgbmV3VnBjUHJvcHMuZW5kcG9pbnRQdWJsaWNBY2Nlc3MgIT09IG9sZFZwY1Byb3BzLmVuZHBvaW50UHVibGljQWNjZXNzIHx8XG4gICAgICAhc2V0c0VxdWFsKG5ld1B1YmxpY0FjY2Vzc0NpZHJzLCBvbGRQdWJsaWNBY2Nlc3NDaWRycyksXG4gICAgcmVwbGFjZVJvbGU6IG5ld1Byb3BzLnJvbGVBcm4gIT09IG9sZFByb3BzLnJvbGVBcm4sXG4gICAgdXBkYXRlVmVyc2lvbjogbmV3UHJvcHMudmVyc2lvbiAhPT0gb2xkUHJvcHMudmVyc2lvbixcbiAgICB1cGRhdGVFbmNyeXB0aW9uOiBKU09OLnN0cmluZ2lmeShuZXdFbmMpICE9PSBKU09OLnN0cmluZ2lmeShvbGRFbmMpLFxuICAgIHVwZGF0ZUxvZ2dpbmc6IEpTT04uc3RyaW5naWZ5KG5ld1Byb3BzLmxvZ2dpbmcpICE9PSBKU09OLnN0cmluZ2lmeShvbGRQcm9wcy5sb2dnaW5nKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2V0c0VxdWFsKGZpcnN0OiBTZXQ8c3RyaW5nPiwgc2Vjb25kOiBTZXQ8c3RyaW5nPikge1xuICByZXR1cm4gZmlyc3Quc2l6ZSA9PT0gc2Vjb25kLnNpemUgJiYgWy4uLmZpcnN0XS5ldmVyeSgoZTogc3RyaW5nKSA9PiBzZWNvbmQuaGFzKGUpKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts deleted file mode 100644 index e6930b7844d32..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5/cluster.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* eslint-disable no-console */ - -// eslint-disable-next-line import/no-extraneous-dependencies -import { IsCompleteResponse, OnEventResponse } from '@aws-cdk/custom-resources/lib/provider-framework/types'; -// eslint-disable-next-line import/no-extraneous-dependencies -import * as aws from 'aws-sdk'; -import { EksClient, ResourceEvent, ResourceHandler } from './common'; - -const MAX_CLUSTER_NAME_LEN = 100; - -export class ClusterResourceHandler extends ResourceHandler { - public get clusterName() { - if (!this.physicalResourceId) { - throw new Error('Cannot determine cluster name without physical resource ID'); - } - - return this.physicalResourceId; - } - - private readonly newProps: aws.EKS.CreateClusterRequest; - private readonly oldProps: Partial; - - constructor(eks: EksClient, event: ResourceEvent) { - super(eks, event); - - this.newProps = parseProps(this.event.ResourceProperties); - this.oldProps = event.RequestType === 'Update' ? parseProps(event.OldResourceProperties) : {}; - } - - // ------ - // CREATE - // ------ - - protected async onCreate(): Promise { - console.log('onCreate: creating cluster with options:', JSON.stringify(this.newProps, undefined, 2)); - if (!this.newProps.roleArn) { - throw new Error('"roleArn" is required'); - } - - const clusterName = this.newProps.name || this.generateClusterName(); - - const resp = await this.eks.createCluster({ - ...this.newProps, - name: clusterName, - }); - - if (!resp.cluster) { - throw new Error(`Error when trying to create cluster ${clusterName}: CreateCluster returned without cluster information`); - } - - return { - PhysicalResourceId: resp.cluster.name, - }; - } - - protected async isCreateComplete() { - return this.isActive(); - } - - // ------ - // DELETE - // ------ - - protected async onDelete(): Promise { - console.log(`onDelete: deleting cluster ${this.clusterName}`); - try { - await this.eks.deleteCluster({ name: this.clusterName }); - } catch (e) { - if (e.code !== 'ResourceNotFoundException') { - throw e; - } else { - console.log(`cluster ${this.clusterName} not found, idempotently succeeded`); - } - } - return { - PhysicalResourceId: this.clusterName, - }; - } - - protected async isDeleteComplete(): Promise { - console.log(`isDeleteComplete: waiting for cluster ${this.clusterName} to be deleted`); - - try { - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster returned:', JSON.stringify(resp, undefined, 2)); - } catch (e) { - if (e.code === 'ResourceNotFoundException') { - console.log('received ResourceNotFoundException, this means the cluster has been deleted (or never existed)'); - return { IsComplete: true }; - } - - console.log('describeCluster error:', e); - throw e; - } - - return { - IsComplete: false, - }; - } - - // ------ - // UPDATE - // ------ - - protected async onUpdate() { - const updates = analyzeUpdate(this.oldProps, this.newProps); - console.log('onUpdate:', JSON.stringify({ updates }, undefined, 2)); - - // updates to encryption config is not supported - if (updates.updateEncryption) { - throw new Error('Cannot update cluster encryption configuration'); - } - - // if there is an update that requires replacement, go ahead and just create - // a new cluster with the new config. The old cluster will automatically be - // deleted by cloudformation upon success. - if (updates.replaceName || updates.replaceRole || updates.replaceVpc) { - - // if we are replacing this cluster and the cluster has an explicit - // physical name, the creation of the new cluster will fail with "there is - // already a cluster with that name". this is a common behavior for - // CloudFormation resources that support specifying a physical name. - if (this.oldProps.name === this.newProps.name && this.oldProps.name) { - throw new Error(`Cannot replace cluster "${this.oldProps.name}" since it has an explicit physical name. Either rename the cluster or remove the "name" configuration`); - } - - return this.onCreate(); - } - - // if a version update is required, issue the version update - if (updates.updateVersion) { - if (!this.newProps.version) { - throw new Error(`Cannot remove cluster version configuration. Current version is ${this.oldProps.version}`); - } - - return this.updateClusterVersion(this.newProps.version); - } - - if (updates.updateLogging && updates.updateAccess) { - throw new Error('Cannot update logging and access at the same time'); - } - - if (updates.updateLogging || updates.updateAccess) { - const config: aws.EKS.UpdateClusterConfigRequest = { - name: this.clusterName, - }; - if (updates.updateLogging) { - config.logging = this.newProps.logging; - }; - if (updates.updateAccess) { - // Updating the cluster with securityGroupIds and subnetIds (as specified in the warning here: - // https://awscli.amazonaws.com/v2/documentation/api/latest/reference/eks/update-cluster-config.html) - // will fail, therefore we take only the access fields explicitly - config.resourcesVpcConfig = { - endpointPrivateAccess: this.newProps.resourcesVpcConfig.endpointPrivateAccess, - endpointPublicAccess: this.newProps.resourcesVpcConfig.endpointPublicAccess, - publicAccessCidrs: this.newProps.resourcesVpcConfig.publicAccessCidrs, - }; - } - const updateResponse = await this.eks.updateClusterConfig(config); - - return { EksUpdateId: updateResponse.update?.id }; - } - - // no updates - return; - } - - protected async isUpdateComplete() { - console.log('isUpdateComplete'); - - // if this is an EKS update, we will monitor the update event itself - if (this.event.EksUpdateId) { - const complete = await this.isEksUpdateComplete(this.event.EksUpdateId); - if (!complete) { - return { IsComplete: false }; - } - - // fall through: if the update is done, we simply delegate to isActive() - // in order to extract attributes and state from the cluster itself, which - // is supposed to be in an ACTIVE state after the update is complete. - } - - return this.isActive(); - } - - private async updateClusterVersion(newVersion: string) { - console.log(`updating cluster version to ${newVersion}`); - - // update-cluster-version will fail if we try to update to the same version, - // so skip in this case. - const cluster = (await this.eks.describeCluster({ name: this.clusterName })).cluster; - if (cluster?.version === newVersion) { - console.log(`cluster already at version ${cluster.version}, skipping version update`); - return; - } - - const updateResponse = await this.eks.updateClusterVersion({ name: this.clusterName, version: newVersion }); - return { EksUpdateId: updateResponse.update?.id }; - } - - private async isActive(): Promise { - console.log('waiting for cluster to become ACTIVE'); - const resp = await this.eks.describeCluster({ name: this.clusterName }); - console.log('describeCluster result:', JSON.stringify(resp, undefined, 2)); - const cluster = resp.cluster; - - // if cluster is undefined (shouldnt happen) or status is not ACTIVE, we are - // not complete. note that the custom resource provider framework forbids - // returning attributes (Data) if isComplete is false. - if (cluster?.status === 'FAILED') { - // not very informative, unfortunately the response doesn't contain any error - // information :\ - throw new Error('Cluster is in a FAILED status'); - } else if (cluster?.status !== 'ACTIVE') { - return { - IsComplete: false, - }; - } else { - return { - IsComplete: true, - Data: { - Name: cluster.name, - Endpoint: cluster.endpoint, - Arn: cluster.arn, - - // IMPORTANT: CFN expects that attributes will *always* have values, - // so return an empty string in case the value is not defined. - // Otherwise, CFN will throw with `Vendor response doesn't contain - // XXXX key`. - - CertificateAuthorityData: cluster.certificateAuthority?.data ?? '', - ClusterSecurityGroupId: cluster.resourcesVpcConfig?.clusterSecurityGroupId ?? '', - OpenIdConnectIssuerUrl: cluster.identity?.oidc?.issuer ?? '', - OpenIdConnectIssuer: cluster.identity?.oidc?.issuer?.substring(8) ?? '', // Strips off https:// from the issuer url - - // We can safely return the first item from encryption configuration array, because it has a limit of 1 item - // https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateCluster.html#AmazonEKS-CreateCluster-request-encryptionConfig - EncryptionConfigKeyArn: cluster.encryptionConfig?.shift()?.provider?.keyArn ?? '', - }, - }; - } - } - - private async isEksUpdateComplete(eksUpdateId: string) { - this.log({ isEksUpdateComplete: eksUpdateId }); - - const describeUpdateResponse = await this.eks.describeUpdate({ - name: this.clusterName, - updateId: eksUpdateId, - }); - - this.log({ describeUpdateResponse }); - - if (!describeUpdateResponse.update) { - throw new Error(`unable to describe update with id "${eksUpdateId}"`); - } - - switch (describeUpdateResponse.update.status) { - case 'InProgress': - return false; - case 'Successful': - return true; - case 'Failed': - case 'Cancelled': - throw new Error(`cluster update id "${eksUpdateId}" failed with errors: ${JSON.stringify(describeUpdateResponse.update.errors)}`); - default: - throw new Error(`unknown status "${describeUpdateResponse.update.status}" for update id "${eksUpdateId}"`); - } - } - - private generateClusterName() { - const suffix = this.requestId.replace(/-/g, ''); // 32 chars - const offset = MAX_CLUSTER_NAME_LEN - suffix.length - 1; - const prefix = this.logicalResourceId.slice(0, offset > 0 ? offset : 0); - return `${prefix}-${suffix}`; - } -} - -function parseProps(props: any): aws.EKS.CreateClusterRequest { - - const parsed = props?.Config ?? {}; - - // this is weird but these boolean properties are passed by CFN as a string, and we need them to be booleanic for the SDK. - // Otherwise it fails with 'Unexpected Parameter: params.resourcesVpcConfig.endpointPrivateAccess is expected to be a boolean' - - if (typeof (parsed.resourcesVpcConfig?.endpointPrivateAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPrivateAccess = parsed.resourcesVpcConfig.endpointPrivateAccess === 'true'; - } - - if (typeof (parsed.resourcesVpcConfig?.endpointPublicAccess) === 'string') { - parsed.resourcesVpcConfig.endpointPublicAccess = parsed.resourcesVpcConfig.endpointPublicAccess === 'true'; - } - - if (typeof (parsed.logging?.clusterLogging[0].enabled) === 'string') { - parsed.logging.clusterLogging[0].enabled = parsed.logging.clusterLogging[0].enabled === 'true'; - } - - return parsed; - -} - -interface UpdateMap { - replaceName: boolean; // name - replaceVpc: boolean; // resourcesVpcConfig.subnetIds and securityGroupIds - replaceRole: boolean; // roleArn - - updateVersion: boolean; // version - updateLogging: boolean; // logging - updateEncryption: boolean; // encryption (cannot be updated) - updateAccess: boolean; // resourcesVpcConfig.endpointPrivateAccess and endpointPublicAccess -} - -function analyzeUpdate(oldProps: Partial, newProps: aws.EKS.CreateClusterRequest): UpdateMap { - console.log('old props: ', JSON.stringify(oldProps)); - console.log('new props: ', JSON.stringify(newProps)); - - const newVpcProps = newProps.resourcesVpcConfig || {}; - const oldVpcProps = oldProps.resourcesVpcConfig || {}; - - const oldPublicAccessCidrs = new Set(oldVpcProps.publicAccessCidrs ?? []); - const newPublicAccessCidrs = new Set(newVpcProps.publicAccessCidrs ?? []); - const newEnc = newProps.encryptionConfig || {}; - const oldEnc = oldProps.encryptionConfig || {}; - - return { - replaceName: newProps.name !== oldProps.name, - replaceVpc: - JSON.stringify(newVpcProps.subnetIds) !== JSON.stringify(oldVpcProps.subnetIds) || - JSON.stringify(newVpcProps.securityGroupIds) !== JSON.stringify(oldVpcProps.securityGroupIds), - updateAccess: - newVpcProps.endpointPrivateAccess !== oldVpcProps.endpointPrivateAccess || - newVpcProps.endpointPublicAccess !== oldVpcProps.endpointPublicAccess || - !setsEqual(newPublicAccessCidrs, oldPublicAccessCidrs), - replaceRole: newProps.roleArn !== oldProps.roleArn, - updateVersion: newProps.version !== oldProps.version, - updateEncryption: JSON.stringify(newEnc) !== JSON.stringify(oldEnc), - updateLogging: JSON.stringify(newProps.logging) !== JSON.stringify(oldProps.logging), - }; -} - -function setsEqual(first: Set, second: Set) { - return first.size === second.size && [...first].every((e: string) => second.has(e)); -} diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py deleted file mode 100644 index a7b26b264118b..0000000000000 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/helm/__init__.py +++ /dev/null @@ -1,189 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import shutil -import tempfile -import zipfile -from urllib.parse import urlparse, unquote - -logger = logging.getLogger() -logger.setLevel(logging.INFO) - -# these are coming from the kubectl layer -os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] - -outdir = os.environ.get('TEST_OUTDIR', '/tmp') -kubeconfig = os.path.join(outdir, 'kubeconfig') - -def get_chart_asset_from_url(chart_asset_url): - chart_zip = os.path.join(outdir, 'chart.zip') - shutil.rmtree(chart_zip, ignore_errors=True) - subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) - chart_dir = os.path.join(outdir, 'chart') - shutil.rmtree(chart_dir, ignore_errors=True) - os.mkdir(chart_dir) - with zipfile.ZipFile(chart_zip, 'r') as zip_ref: - zip_ref.extractall(chart_dir) - return chart_dir - -def helm_handler(event, context): - logger.info(json.dumps(dict(event, ResponseURL='...'))) - - request_type = event['RequestType'] - props = event['ResourceProperties'] - - # resource properties - cluster_name = props['ClusterName'] - role_arn = props['RoleArn'] - release = props['Release'] - chart = props.get('Chart', None) - chart_asset_url = props.get('ChartAssetURL', None) - version = props.get('Version', None) - wait = props.get('Wait', False) - timeout = props.get('Timeout', None) - namespace = props.get('Namespace', None) - create_namespace = props.get('CreateNamespace', None) - repository = props.get('Repository', None) - values_text = props.get('Values', None) - - # "log in" to the cluster - subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', - '--role-arn', role_arn, - '--name', cluster_name, - '--kubeconfig', kubeconfig - ]) - - if os.path.isfile(kubeconfig): - os.chmod(kubeconfig, 0o600) - - # Write out the values to a file and include them with the install and upgrade - values_file = None - if not request_type == "Delete" and not values_text is None: - values = json.loads(values_text) - values_file = os.path.join(outdir, 'values.yaml') - with open(values_file, "w") as f: - f.write(json.dumps(values, indent=2)) - - if request_type == 'Create' or request_type == 'Update': - # Ensure chart or chart_asset_url are set - if chart == None and chart_asset_url == None: - raise RuntimeError(f'chart or chartAsset must be specified') - - if chart_asset_url != None: - assert(chart==None) - assert(repository==None) - assert(version==None) - if not chart_asset_url.startswith('s3://'): - raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') - # 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, repository, version) - chart = chart_dir - - helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) - elif request_type == "Delete": - try: - helm('uninstall', release, namespace=namespace, timeout=timeout) - except Exception as e: - logger.info("delete error: %s" % e) - - -def get_oci_cmd(repository, version): - # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. - cmnd = [] - private_ecr_pattern = '\d+.dkr.ecr.[a-z]+-[a-z]+-\d.amazonaws.com' - public_ecr = 'public.ecr.aws' - - registry = repository.rsplit('/', 1)[0].replace('oci://', '') - - if re.fullmatch(private_ecr_pattern, registry) is not None: - logger.info("Found AWS private repository") - 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" - ] - elif registry.startswith(public_ecr): - logger.info("Found AWS public repository, will use default region as deployment") - region = os.environ.get('AWS_REGION', 'us-east-1') - - cmnd = [ - f"aws ecr-public get-login-password --region {region} | " \ - f"helm registry login --username AWS --password-stdin {public_ecr}; helm pull {repository} --version {version} --untar" - ] - else: - logger.error("OCI repository format not recognized, falling back to helm pull") - cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] - - return cmnd - - -def get_chart_from_oci(tmpdir, repository = None, version = None): - - cmnd = get_oci_cmd(repository, version) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - logger.info(cmnd) - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) - logger.info(output) - - # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. - # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service - return os.path.join(tmpdir, repository.rpartition('/')[-1]) - 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): - import subprocess - - cmnd = ['helm', verb, release] - if not chart is None: - cmnd.append(chart) - if verb == 'upgrade': - cmnd.append('--install') - if create_namespace: - cmnd.append('--create-namespace') - if not repo is None: - cmnd.extend(['--repo', repo]) - if not file is None: - cmnd.extend(['--values', file]) - if not version is None: - cmnd.extend(['--version', version]) - if not namespace is None: - cmnd.extend(['--namespace', namespace]) - if wait: - cmnd.append('--wait') - if not timeout is None: - cmnd.extend(['--timeout', timeout]) - cmnd.extend(['--kubeconfig', kubeconfig]) - - maxAttempts = 3 - retry = maxAttempts - while retry > 0: - try: - output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) - logger.info(output) - return - 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}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip index ce3ea448ac19d..13983109fc5f5 100644 Binary files a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip and b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1.zip differ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/apply/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/apply/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/get/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/get/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py new file mode 100644 index 0000000000000..286976ced219a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/helm/__init__.py @@ -0,0 +1,187 @@ +import json +import logging +import os +import re +import subprocess +import shutil +import tempfile +import zipfile + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +# these are coming from the kubectl layer +os.environ['PATH'] = '/opt/helm:/opt/awscli:' + os.environ['PATH'] + +outdir = os.environ.get('TEST_OUTDIR', '/tmp') +kubeconfig = os.path.join(outdir, 'kubeconfig') + +def get_chart_asset_from_url(chart_asset_url): + chart_zip = os.path.join(outdir, 'chart.zip') + shutil.rmtree(chart_zip, ignore_errors=True) + subprocess.check_call(['aws', 's3', 'cp', chart_asset_url, chart_zip]) + chart_dir = os.path.join(outdir, 'chart') + shutil.rmtree(chart_dir, ignore_errors=True) + os.mkdir(chart_dir) + with zipfile.ZipFile(chart_zip, 'r') as zip_ref: + zip_ref.extractall(chart_dir) + return chart_dir + +def helm_handler(event, context): + logger.info(json.dumps(dict(event, ResponseURL='...'))) + + request_type = event['RequestType'] + props = event['ResourceProperties'] + + # resource properties + cluster_name = props['ClusterName'] + role_arn = props['RoleArn'] + release = props['Release'] + chart = props.get('Chart', None) + chart_asset_url = props.get('ChartAssetURL', None) + version = props.get('Version', None) + wait = props.get('Wait', False) + timeout = props.get('Timeout', None) + namespace = props.get('Namespace', None) + create_namespace = props.get('CreateNamespace', None) + repository = props.get('Repository', None) + values_text = props.get('Values', None) + + # "log in" to the cluster + subprocess.check_call([ 'aws', 'eks', 'update-kubeconfig', + '--role-arn', role_arn, + '--name', cluster_name, + '--kubeconfig', kubeconfig + ]) + + if os.path.isfile(kubeconfig): + os.chmod(kubeconfig, 0o600) + + # Write out the values to a file and include them with the install and upgrade + values_file = None + if not request_type == "Delete" and not values_text is None: + values = json.loads(values_text) + values_file = os.path.join(outdir, 'values.yaml') + with open(values_file, "w") as f: + f.write(json.dumps(values, indent=2)) + + if request_type == 'Create' or request_type == 'Update': + # Ensure chart or chart_asset_url are set + if chart == None and chart_asset_url == None: + raise RuntimeError(f'chart or chartAsset must be specified') + + if chart_asset_url != None: + assert(chart==None) + assert(repository==None) + assert(version==None) + if not chart_asset_url.startswith('s3://'): + raise RuntimeError(f'ChartAssetURL must point to as s3 location but is {chart_asset_url}') + # 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, repository, version) + chart = chart_dir + + helm('upgrade', release, chart, repository, values_file, namespace, version, wait, timeout, create_namespace) + elif request_type == "Delete": + try: + helm('uninstall', release, namespace=namespace, timeout=timeout) + except Exception as e: + logger.info("delete error: %s" % e) + + +def get_oci_cmd(repository, version): + # Generates OCI command based on pattern. Public ECR vs Private ECR are treated differently. + private_ecr_pattern = 'oci://(?P\d+.dkr.ecr.(?P[a-z]+-[a-z]+-\d).amazonaws.com)*' + public_ecr_pattern = 'oci://(?Ppublic.ecr.aws)*' + + private_registry = re.match(private_ecr_pattern, repository).groupdict() + public_registry = re.match(public_ecr_pattern, repository).groupdict() + + if private_registry['registry'] is not None: + logger.info("Found AWS private repository") + cmnd = [ + f"aws ecr get-login-password --region {private_registry['region']} | " \ + f"helm registry login --username AWS --password-stdin {private_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + elif public_registry['registry'] is not None: + logger.info("Found AWS public repository, will use default region as deployment") + region = os.environ.get('AWS_REGION', 'us-east-1') + + cmnd = [ + f"aws ecr-public get-login-password --region us-east-1 | " \ + f"helm registry login --username AWS --password-stdin {public_registry['registry']}; helm pull {repository} --version {version} --untar" + ] + else: + logger.error("OCI repository format not recognized, falling back to helm pull") + cmnd = ['helm', 'pull', repository, '--version', version, '--untar'] + + return cmnd + + +def get_chart_from_oci(tmpdir, repository = None, version = None): + + cmnd = get_oci_cmd(repository, version) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + logger.info(cmnd) + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=tmpdir, shell=True) + logger.info(output) + + # effectively returns "$tmpDir/$lastPartOfOCIUrl", because this is how helm pull saves OCI artifact. + # Eg. if we have oci://9999999999.dkr.ecr.us-east-1.amazonaws.com/foo/bar/pet-service repository, helm saves artifact under $tmpDir/pet-service + return os.path.join(tmpdir, repository.rpartition('/')[-1]) + 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 helm(verb, release, chart = None, repo = None, file = None, namespace = None, version = None, wait = False, timeout = None, create_namespace = None): + import subprocess + + cmnd = ['helm', verb, release] + if not chart is None: + cmnd.append(chart) + if verb == 'upgrade': + cmnd.append('--install') + if create_namespace: + cmnd.append('--create-namespace') + if not repo is None: + cmnd.extend(['--repo', repo]) + if not file is None: + cmnd.extend(['--values', file]) + if not version is None: + cmnd.extend(['--version', version]) + if not namespace is None: + cmnd.extend(['--namespace', namespace]) + if wait: + cmnd.append('--wait') + if not timeout is None: + cmnd.extend(['--timeout', timeout]) + cmnd.extend(['--kubeconfig', kubeconfig]) + + maxAttempts = 3 + retry = maxAttempts + while retry > 0: + try: + output = subprocess.check_output(cmnd, stderr=subprocess.STDOUT, cwd=outdir) + logger.info(output) + return + 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}') diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/index.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/index.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py similarity index 100% rename from packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd/patch/__init__.py rename to packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8/patch/__init__.py diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json index 1e3ca12d1507f..0b979f6032486 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "ad44c2b0638f04871c889d78e71dea90ffae67b9cc4aa4366d5102db42435ee1": { "source": { @@ -14,15 +14,15 @@ } } }, - "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5": { + "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee": { "source": { - "path": "asset.76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5", + "path": "asset.42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip", + "objectKey": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -40,15 +40,15 @@ } } }, - "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd": { + "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8": { "source": { - "path": "asset.a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd", + "path": "asset.c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8", "packaging": "zip" }, "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip", + "objectKey": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } @@ -105,7 +105,7 @@ } } }, - "f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8": { + "d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4": { "source": { "path": "awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json", "packaging": "file" @@ -113,12 +113,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json", + "objectKey": "d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e": { + "e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33": { "source": { "path": "awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json", "packaging": "file" @@ -126,12 +126,12 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json", + "objectKey": "e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } }, - "e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e": { + "6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90": { "source": { "path": "aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json", "packaging": "file" @@ -139,7 +139,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e.json", + "objectKey": "6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json index c1627f1b76a6b..3e2c2241e73ec 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/aws-stepfunctions-tasks-emr-containers-start-job-run-test.template.json @@ -980,7 +980,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json" + "/d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json" ] ] }, @@ -1015,7 +1015,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json" + "/e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json" ] ] }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json index d458abf6274ab..3a39787a6ccf1 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobrunDefaultTestDeployAssert0C0D5C7F.assets.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json index 06eef5274ca63..d6a92efeec8a2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksClusterResourceProvider2391B7F7.nested.template.json @@ -73,7 +73,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ @@ -162,7 +162,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "S3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json index 603f101ac4aa1..e18726ae92e89 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/awsstepfunctionstasksemrcontainersstartjobruntestawscdkawseksKubectlProviderEB85BF5A.nested.template.json @@ -51,6 +51,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -92,7 +104,7 @@ "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "S3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "S3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "Role": { "Fn::GetAtt": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out index ae4b03c54e770..b72fef144f05c 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"30.1.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json index 23859f1ee4f00..b97117768e83d 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "testCases": { "aws-stepfunctions-tasks-emr-containers-start-job-run/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json index d8c9b2b4f4be5..60e1218926392 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "30.1.0", "artifacts": { "aws-stepfunctions-tasks-emr-containers-start-job-run-test.assets": { "type": "cdk:asset-manifest", @@ -17,7 +17,7 @@ "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}/e6eaca5f95d8be16472cdbd60817d3e874e920852d04c07132fa19e7d6be6e9e.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6953b4416f5110b908a0830d060a2ddcbb7af91e54cabc9231ddbc773f7a3e90.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json index 8a1f2ae75f6c1..b180568b42669 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/emrcontainers/integ.start-job-run.js.snapshot/tree.json @@ -960,7 +960,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "KubectlReadyBarrier": { @@ -1482,7 +1482,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -1655,7 +1655,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "76b95b763a0d19e172361b0123e88b00854f56785669102a9ab0127f4f738bf5.zip" + "s3Key": "42ee7a787eab7842c3d815365d104cacb9168fb9beb8a1bc019b0a6d7e969bee.zip" }, "role": { "Fn::GetAtt": [ @@ -2496,7 +2496,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, @@ -2553,7 +2553,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/f61e6013fd4f150889ad36f3bb7e03ff8bb8ec47c6246f1aa662f111b6229ae8.json" + "/d808c7b09f17a5b8142a9ee7eff4287d5ce8461eced11312cb8d647602e4f2f4.json" ] ] }, @@ -2575,7 +2575,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "@aws-cdk--aws-eks.KubectlProvider": { @@ -2652,6 +2652,18 @@ ":iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" ] ] + }, + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/AmazonElasticContainerRegistryPublicReadOnly" + ] + ] } ] } @@ -2751,7 +2763,7 @@ "s3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "s3Key": "a0738c4112d1f07ba7bbb4891a2efc3b998d66ef82238a7839f604d4f6a198fd.zip" + "s3Key": "c17e6c5822dd39738b3ba669bef4bb7c8fceaea76b51477bf94d6745d0c201c8.zip" }, "role": { "Fn::GetAtt": [ @@ -3221,7 +3233,7 @@ { "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" }, - "/2c4bbd9bfdca8d0c8d329000c43b16b2ec52206c08b4027657c1d76a41a4185e.json" + "/e5f80caa912def8e04aa645be0d878c4be62a3c71e5ed2335f37702f0e365e33.json" ] ] }, @@ -3261,7 +3273,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "Virtual Cluster": { @@ -4327,7 +4339,7 @@ "path": "aws-stepfunctions-tasks-emr-containers-start-job-run/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } }, "DeployAssert": { @@ -4373,7 +4385,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.1.237" + "version": "10.1.252" } } }, diff --git a/packages/@aws-cdk/cfnspec/lib/schema/property.ts b/packages/@aws-cdk/cfnspec/lib/schema/property.ts index 5278b6300190f..d78e99971198e 100644 --- a/packages/@aws-cdk/cfnspec/lib/schema/property.ts +++ b/packages/@aws-cdk/cfnspec/lib/schema/property.ts @@ -96,7 +96,7 @@ export interface MapOfListsOfPrimitives extends MapPropertyBase { } export interface TagPropertyStandard extends PropertyBase { - ItemType: 'Tag' | 'TagsEntry' | 'TagRef' | 'ElasticFileSystemTag' | 'HostedZoneTag'; + ItemType: 'Tag' | 'TagsEntry' | 'TagRef' | 'ElasticFileSystemTag' | 'HostedZoneTag' | 'AccessPointTag'; Type: 'Tags'; } @@ -256,6 +256,7 @@ const tagPropertyNames = { HostedZoneTags: '', Tags: '', UserPoolTags: '', + AccessPointTags: '', }; export type TagPropertyName = keyof typeof tagPropertyNames; @@ -288,7 +289,8 @@ export function isTagPropertyStandard(prop: Property): prop is TagPropertyStanda (prop as TagPropertyStandard).Type === 'Tags' || (prop as TagPropertyStandard).ItemType === 'TagRef' || (prop as TagPropertyStandard).ItemType === 'ElasticFileSystemTag' || - (prop as TagPropertyStandard).ItemType === 'HostedZoneTag' + (prop as TagPropertyStandard).ItemType === 'HostedZoneTag' || + (prop as TagPropertyStandard).ItemType === 'AccessPointTag' ); } diff --git a/packages/@aws-cdk/cfnspec/lib/schema/resource-type.ts b/packages/@aws-cdk/cfnspec/lib/schema/resource-type.ts index 8a33571504545..0e817500bfeec 100644 --- a/packages/@aws-cdk/cfnspec/lib/schema/resource-type.ts +++ b/packages/@aws-cdk/cfnspec/lib/schema/resource-type.ts @@ -34,6 +34,7 @@ export interface TaggableResource extends ResourceType { HostedZoneTags: TagProperty; Tags: TagProperty; UserPoolTags: TagProperty; + AccessPointTags: TagProperty; [name: string]: Property; } } 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 7953c7a1a0761..51cb135d5d5ad 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 @@ -1036,7 +1036,7 @@ "Id": "The ID for the account. For example: `abc123` .", "Ref": "`Ref` returns the ID of the resource, such as `mysta-accou-01234b567890example` ." }, - "description": "The `AWS::ApiGateway::Account` resource specifies the IAM role that Amazon API Gateway uses to write API logs to Amazon CloudWatch Logs.\n\n> If an API Gateway resource has never been created in your AWS account , you must add a dependency on another API Gateway resource, such as an [AWS::ApiGateway::RestApi](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html) or [AWS::ApiGateway::ApiKey](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html) resource.\n> \n> If an API Gateway resource has been created in your AWS account , no dependency is required (even if the resource was deleted).", + "description": "The `AWS::ApiGateway::Account` resource specifies the IAM role that Amazon API Gateway uses to write API logs to Amazon CloudWatch Logs. To avoid overwriting other roles, you should only have one `AWS::ApiGateway::Account` resource per region per account.\n\n> If an API Gateway resource has never been created in your AWS account , you must add a dependency on another API Gateway resource, such as an [AWS::ApiGateway::RestApi](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-restapi.html) or [AWS::ApiGateway::ApiKey](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-apikey.html) resource.\n> \n> If an API Gateway resource has been created in your AWS account , no dependency is required (even if the resource was deleted).", "properties": { "CloudWatchRoleArn": "The ARN of an Amazon CloudWatch role for the current Account." } @@ -1370,7 +1370,7 @@ "AWS::ApiGateway::RestApi": { "attributes": { "Ref": "`Ref` returns the `RestApi` ID, such as `a1bcdef2gh` .", - "RestApiId": "", + "RestApiId": "The string identifier of the associated RestApi.", "RootResourceId": "The root resource ID for a `RestApi` resource, such as `a0bc123d4e` ." }, "description": "The `AWS::ApiGateway::RestApi` resource creates a REST API. For more information, see [restapi:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateRestApi.html) in the *Amazon API Gateway REST API Reference* .\n\n> On January 1, 2016, the Swagger Specification was donated to the [OpenAPI initiative](https://docs.aws.amazon.com/https://www.openapis.org/) , becoming the foundation of the OpenAPI Specification.", @@ -1521,7 +1521,8 @@ }, "AWS::ApiGateway::VpcLink": { "attributes": { - "Ref": "`Ref` returns the ID of the `VpcLink` ." + "Ref": "`Ref` returns the ID of the `VpcLink` .", + "VpcLinkId": "" }, "description": "The `AWS::ApiGateway::VpcLink` resource creates an API Gateway VPC link for a REST API to access resources in an Amazon Virtual Private Cloud (VPC). For more information, see [vpclink:create](https://docs.aws.amazon.com/apigateway/latest/api/API_CreateVpcLink.html) in the `Amazon API Gateway REST API Reference` .", "properties": { @@ -1833,8 +1834,7 @@ }, "AWS::ApiGatewayV2::RouteResponse": { "attributes": { - "Ref": "`Ref` returns the Route Response resource ID, such as `abc123` .", - "RouteResponseId": "" + "Ref": "`Ref` returns the Route Response resource ID, such as `abc123` ." }, "description": "The `AWS::ApiGatewayV2::RouteResponse` resource creates a route response for a WebSocket API. For more information, see [Set up Route Responses for a WebSocket API in API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-route-response.html) in the *API Gateway Developer Guide* .", "properties": { @@ -1846,6 +1846,13 @@ "RouteResponseKey": "The route response key." } }, + "AWS::ApiGatewayV2::RouteResponse.ParameterConstraints": { + "attributes": {}, + "description": "Specifies whether the parameter is required.", + "properties": { + "Required": "Specifies whether the parameter is required." + } + }, "AWS::ApiGatewayV2::Stage": { "attributes": { "Ref": "`Ref` returns the stage name, such as `MyTestStage` ." @@ -2037,7 +2044,8 @@ "Content": "The content of the configuration or the configuration data.", "ContentType": "A standard MIME type describing the format of the configuration content. For more information, see [Content-Type](https://docs.aws.amazon.com/https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17) .", "Description": "A description of the configuration.", - "LatestVersionNumber": "An optional locking token used to prevent race conditions from overwriting configuration updates when creating a new version. To ensure your data is not overwritten when creating multiple hosted configuration versions in rapid succession, specify the version number of the latest hosted configuration version." + "LatestVersionNumber": "An optional locking token used to prevent race conditions from overwriting configuration updates when creating a new version. To ensure your data is not overwritten when creating multiple hosted configuration versions in rapid succession, specify the version number of the latest hosted configuration version.", + "VersionLabel": "A user-defined label for an AWS AppConfig hosted configuration version." } }, "AWS::AppFlow::Connector": { @@ -2050,7 +2058,7 @@ "ConnectorLabel": "The label used for registering the connector.", "ConnectorProvisioningConfig": "The configuration required for registering the connector.", "ConnectorProvisioningType": "The provisioning type used to register the connector.", - "Description": "A description of the connector entity field." + "Description": "A description about the connector runtime setting." } }, "AWS::AppFlow::Connector.ConnectorProvisioningConfig": { @@ -2341,13 +2349,13 @@ "properties": { "BucketName": "A name for the associated Amazon S3 bucket.", "BucketPrefix": "The object key for the destination bucket in which Amazon AppFlow places the files.", - "ClusterIdentifier": "The unique ID that's assigned to an Amazon Redshift cluster.", - "DataApiRoleArn": "The Amazon Resource Name (ARN) of an IAM role that permits Amazon AppFlow to access your Amazon Redshift database through the Data API. For more information, and for the polices that you attach to this role, see [Allow Amazon AppFlow to access Amazon Redshift databases with the Data API](https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_service-role-policies.html#access-redshift) .", - "DatabaseName": "The name of an Amazon Redshift database.", + "ClusterIdentifier": "", + "DataApiRoleArn": "", + "DatabaseName": "", "DatabaseUrl": "The JDBC URL of the Amazon Redshift cluster.", - "IsRedshiftServerless": "Indicates whether the connector profile defines a connection to an Amazon Redshift Serverless data warehouse.", + "IsRedshiftServerless": "", "RoleArn": "The Amazon Resource Name (ARN) of IAM role that grants Amazon Redshift read-only access to Amazon S3. For more information, and for the polices that you attach to this role, see [Allow Amazon Redshift to access your Amazon AppFlow data in Amazon S3](https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_service-role-policies.html#redshift-access-s3) .", - "WorkgroupName": "The name of an Amazon Redshift workgroup." + "WorkgroupName": "" } }, "AWS::AppFlow::ConnectorProfile.SAPODataConnectorProfileCredentials": { @@ -2511,7 +2519,7 @@ "description": "The aggregation settings that you can use to customize the output format of your flow data.", "properties": { "AggregationType": "Specifies whether Amazon AppFlow aggregates the flow records into a single file, or leave them unaggregated.", - "TargetFileSize": "The desired file size, in MB, for each output file that Amazon AppFlow writes to the flow destination. For each file, Amazon AppFlow attempts to achieve the size that you specify. The actual file sizes might differ from this target based on the number and size of the records that each file contains." + "TargetFileSize": "" } }, "AWS::AppFlow::Flow.AmplitudeSourceProperties": { @@ -2675,9 +2683,9 @@ }, "AWS::AppFlow::Flow.MetadataCatalogConfig": { "attributes": {}, - "description": "Specifies the configuration that Amazon AppFlow uses when it catalogs your data. When Amazon AppFlow catalogs your data, it stores metadata in a data catalog.", + "description": "", "properties": { - "GlueDataCatalog": "Specifies the configuration that Amazon AppFlow uses when it catalogs your data with the AWS Glue Data Catalog ." + "GlueDataCatalog": "" } }, "AWS::AppFlow::Flow.PardotSourceProperties": { @@ -2691,7 +2699,7 @@ "attributes": {}, "description": "Specifies elements that Amazon AppFlow includes in the file and folder names in the flow destination.", "properties": { - "PathPrefixHierarchy": "Specifies whether the destination file path includes either or both of the following elements:\n\n- **EXECUTION_ID** - The ID that Amazon AppFlow assigns to the flow run.\n- **SCHEMA_VERSION** - The version number of your data schema. Amazon AppFlow assigns this version number. The version number increases by one when you change any of the following settings in your flow configuration:\n\n- Source-to-destination field mappings\n- Field data types\n- Partition keys", + "PathPrefixHierarchy": "", "PrefixFormat": "Determines the level of granularity for the date and time that's included in the prefix.", "PrefixType": "Determines the format of the prefix, and whether it applies to the file name, file path, or both." } @@ -2854,7 +2862,7 @@ "properties": { "ApiVersion": "The API version of the connector when it's used as a source in the flow.", "ConnectorProfileName": "The name of the connector profile. This name must be unique for each connector profile in the AWS account .", - "ConnectorType": "The type of source connector, such as Salesforce, Amplitude, and so on.\n\n*Allowed Values* : S3 | Amplitude | Datadog | Dynatrace | Googleanalytics | Infornexus | Salesforce | Servicenow | Singular | Slack | Trendmicro | Veeva | Zendesk", + "ConnectorType": "The type of connector, such as Salesforce, Amplitude, and so on.", "IncrementalPullConfig": "Defines the configuration for a scheduled incremental data pull. If a valid configuration is provided, the fields specified in the configuration are used when querying for the incremental data pull.", "SourceConnectorProperties": "Specifies the information that is required to query a particular source connector." } @@ -7738,55 +7746,55 @@ "LastModifiedTime": "The date and time when the cache policy was last modified.", "Ref": "`Ref` returns the cache policy ID. For example: `2766f7b2-75c5-41c6-8f06-bf4303a2f2f5` ." }, - "description": "A cache policy.\n\nWhen it's attached to a cache behavior, the cache policy determines the following:\n\n- The values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n- The default, minimum, and maximum time to live (TTL) values that you want objects to stay in the CloudFront cache.\n\nThe headers, cookies, and query strings that are included in the cache key are automatically included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find a valid object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", + "description": "A cache policy.\n\nWhen it's attached to a cache behavior, the cache policy determines the following:\n\n- The values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n- The default, minimum, and maximum time to live (TTL) values that you want objects to stay in the CloudFront cache.\n\nThe headers, cookies, and query strings that are included in the cache key are also included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find a valid object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", "properties": { "CachePolicyConfig": "The cache policy configuration." } }, "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "attributes": {}, - "description": "A cache policy configuration.\n\nThis configuration determines the following:\n\n- The values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n- The default, minimum, and maximum time to live (TTL) values that you want objects to stay in the CloudFront cache.\n\nThe headers, cookies, and query strings that are included in the cache key are automatically included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find a valid object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", + "description": "A cache policy configuration.\n\nThis configuration determines the following:\n\n- The values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n- The default, minimum, and maximum time to live (TTL) values that you want objects to stay in the CloudFront cache.\n\nThe headers, cookies, and query strings that are included in the cache key are also included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find a valid object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", "properties": { "Comment": "A comment to describe the cache policy. The comment cannot be longer than 128 characters.", "DefaultTTL": "The default amount of time, in seconds, that you want objects to stay in the CloudFront cache before CloudFront sends another request to the origin to see if the object has been updated. CloudFront uses this value as the object's time to live (TTL) only when the origin does *not* send `Cache-Control` or `Expires` headers with the object. For more information, see [Managing How Long Content Stays in an Edge Cache (Expiration)](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) in the *Amazon CloudFront Developer Guide* .\n\nThe default value for this field is 86400 seconds (one day). If the value of `MinTTL` is more than 86400 seconds, then the default value for this field is the same as the value of `MinTTL` .", "MaxTTL": "The maximum amount of time, in seconds, that objects stay in the CloudFront cache before CloudFront sends another request to the origin to see if the object has been updated. CloudFront uses this value only when the origin sends `Cache-Control` or `Expires` headers with the object. For more information, see [Managing How Long Content Stays in an Edge Cache (Expiration)](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) in the *Amazon CloudFront Developer Guide* .\n\nThe default value for this field is 31536000 seconds (one year). If the value of `MinTTL` or `DefaultTTL` is more than 31536000 seconds, then the default value for this field is the same as the value of `DefaultTTL` .", "MinTTL": "The minimum amount of time, in seconds, that you want objects to stay in the CloudFront cache before CloudFront sends another request to the origin to see if the object has been updated. For more information, see [Managing How Long Content Stays in an Edge Cache (Expiration)](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) in the *Amazon CloudFront Developer Guide* .", "Name": "A unique name to identify the cache policy.", - "ParametersInCacheKeyAndForwardedToOrigin": "The HTTP headers, cookies, and URL query strings to include in the cache key. The values included in the cache key are automatically included in requests that CloudFront sends to the origin." + "ParametersInCacheKeyAndForwardedToOrigin": "The HTTP headers, cookies, and URL query strings to include in the cache key. The values included in the cache key are also included in requests that CloudFront sends to the origin." } }, "AWS::CloudFront::CachePolicy.CookiesConfig": { "attributes": {}, - "description": "An object that determines whether any cookies in viewer requests (and if so, which cookies) are included in the cache key and automatically included in requests that CloudFront sends to the origin.", + "description": "An object that determines whether any cookies in viewer requests (and if so, which cookies) are included in the cache key and in requests that CloudFront sends to the origin.", "properties": { - "CookieBehavior": "Determines whether any cookies in viewer requests are included in the cache key and automatically included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 Cookies in viewer requests are not included in the cache key and are not automatically included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any cookies that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 The cookies in viewer requests that are listed in the `CookieNames` type are included in the cache key and automatically included in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All cookies in viewer requests that are **not** listed in the `CookieNames` type are included in the cache key and automatically included in requests that CloudFront sends to the origin.\n- `all` \u2013 All cookies in viewer requests are included in the cache key and are automatically included in requests that CloudFront sends to the origin.", + "CookieBehavior": "Determines whether any cookies in viewer requests are included in the cache key and in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No cookies in viewer requests are included in the cache key or in requests that CloudFront sends to the origin. Even when this field is set to `none` , any cookies that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the cookies in viewer requests that are listed in the `CookieNames` type are included in the cache key and in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All cookies in viewer requests are included in the cache key and in requests that CloudFront sends to the origin, **except** for those that are listed in the `CookieNames` type, which are not included.\n- `all` \u2013 All cookies in viewer requests are included in the cache key and in requests that CloudFront sends to the origin.", "Cookies": "Contains a list of cookie names." } }, "AWS::CloudFront::CachePolicy.HeadersConfig": { "attributes": {}, - "description": "An object that determines whether any HTTP headers (and if so, which headers) are included in the cache key and automatically included in requests that CloudFront sends to the origin.", + "description": "An object that determines whether any HTTP headers (and if so, which headers) are included in the cache key and in requests that CloudFront sends to the origin.", "properties": { - "HeaderBehavior": "Determines whether any HTTP headers are included in the cache key and automatically included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 HTTP headers are not included in the cache key and are not automatically included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any headers that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 The HTTP headers that are listed in the `Headers` type are included in the cache key and are automatically included in requests that CloudFront sends to the origin.", + "HeaderBehavior": "Determines whether any HTTP headers are included in the cache key and in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No HTTP headers are included in the cache key or in requests that CloudFront sends to the origin. Even when this field is set to `none` , any headers that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the HTTP headers that are listed in the `Headers` type are included in the cache key and in requests that CloudFront sends to the origin.", "Headers": "Contains a list of HTTP header names." } }, "AWS::CloudFront::CachePolicy.ParametersInCacheKeyAndForwardedToOrigin": { "attributes": {}, - "description": "This object determines the values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n\nThe headers, cookies, and query strings that are included in the cache key are automatically included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find an object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", + "description": "This object determines the values that CloudFront includes in the cache key. These values can include HTTP headers, cookies, and URL query strings. CloudFront uses the cache key to find an object in its cache that it can return to the viewer.\n\nThe headers, cookies, and query strings that are included in the cache key are also included in requests that CloudFront sends to the origin. CloudFront sends a request when it can't find an object in its cache that matches the request's cache key. If you want to send values to the origin but *not* include them in the cache key, use `OriginRequestPolicy` .", "properties": { - "CookiesConfig": "An object that determines whether any cookies in viewer requests (and if so, which cookies) are included in the cache key and automatically included in requests that CloudFront sends to the origin.", + "CookiesConfig": "An object that determines whether any cookies in viewer requests (and if so, which cookies) are included in the cache key and in requests that CloudFront sends to the origin.", "EnableAcceptEncodingBrotli": "A flag that can affect whether the `Accept-Encoding` HTTP header is included in the cache key and included in requests that CloudFront sends to the origin.\n\nThis field is related to the `EnableAcceptEncodingGzip` field. If one or both of these fields is `true` *and* the viewer request includes the `Accept-Encoding` header, then CloudFront does the following:\n\n- Normalizes the value of the viewer's `Accept-Encoding` header\n- Includes the normalized header in the cache key\n- Includes the normalized header in the request to the origin, if a request is necessary\n\nFor more information, see [Compression support](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html#cache-policy-compressed-objects) in the *Amazon CloudFront Developer Guide* .\n\nIf you set this value to `true` , and this cache behavior also has an origin request policy attached, do not include the `Accept-Encoding` header in the origin request policy. CloudFront always includes the `Accept-Encoding` header in origin requests when the value of this field is `true` , so including this header in an origin request policy has no effect.\n\nIf both of these fields are `false` , then CloudFront treats the `Accept-Encoding` header the same as any other HTTP header in the viewer request. By default, it's not included in the cache key and it's not included in origin requests. In this case, you can manually add `Accept-Encoding` to the headers whitelist like any other HTTP header.", "EnableAcceptEncodingGzip": "A flag that can affect whether the `Accept-Encoding` HTTP header is included in the cache key and included in requests that CloudFront sends to the origin.\n\nThis field is related to the `EnableAcceptEncodingBrotli` field. If one or both of these fields is `true` *and* the viewer request includes the `Accept-Encoding` header, then CloudFront does the following:\n\n- Normalizes the value of the viewer's `Accept-Encoding` header\n- Includes the normalized header in the cache key\n- Includes the normalized header in the request to the origin, if a request is necessary\n\nFor more information, see [Compression support](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html#cache-policy-compressed-objects) in the *Amazon CloudFront Developer Guide* .\n\nIf you set this value to `true` , and this cache behavior also has an origin request policy attached, do not include the `Accept-Encoding` header in the origin request policy. CloudFront always includes the `Accept-Encoding` header in origin requests when the value of this field is `true` , so including this header in an origin request policy has no effect.\n\nIf both of these fields are `false` , then CloudFront treats the `Accept-Encoding` header the same as any other HTTP header in the viewer request. By default, it's not included in the cache key and it's not included in origin requests. In this case, you can manually add `Accept-Encoding` to the headers whitelist like any other HTTP header.", - "HeadersConfig": "An object that determines whether any HTTP headers (and if so, which headers) are included in the cache key and automatically included in requests that CloudFront sends to the origin.", - "QueryStringsConfig": "An object that determines whether any URL query strings in viewer requests (and if so, which query strings) are included in the cache key and automatically included in requests that CloudFront sends to the origin." + "HeadersConfig": "An object that determines whether any HTTP headers (and if so, which headers) are included in the cache key and in requests that CloudFront sends to the origin.", + "QueryStringsConfig": "An object that determines whether any URL query strings in viewer requests (and if so, which query strings) are included in the cache key and in requests that CloudFront sends to the origin." } }, "AWS::CloudFront::CachePolicy.QueryStringsConfig": { "attributes": {}, - "description": "An object that determines whether any URL query strings in viewer requests (and if so, which query strings) are included in the cache key and automatically included in requests that CloudFront sends to the origin.", + "description": "An object that determines whether any URL query strings in viewer requests (and if so, which query strings) are included in the cache key and in requests that CloudFront sends to the origin.", "properties": { - "QueryStringBehavior": "Determines whether any URL query strings in viewer requests are included in the cache key and automatically included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 Query strings in viewer requests are not included in the cache key and are not automatically included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any query strings that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 The query strings in viewer requests that are listed in the `QueryStringNames` type are included in the cache key and automatically included in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All query strings in viewer requests that are **not** listed in the `QueryStringNames` type are included in the cache key and automatically included in requests that CloudFront sends to the origin.\n- `all` \u2013 All query strings in viewer requests are included in the cache key and are automatically included in requests that CloudFront sends to the origin.", + "QueryStringBehavior": "Determines whether any URL query strings in viewer requests are included in the cache key and in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No query strings in viewer requests are included in the cache key or in requests that CloudFront sends to the origin. Even when this field is set to `none` , any query strings that are listed in an `OriginRequestPolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the query strings in viewer requests that are listed in the `QueryStringNames` type are included in the cache key and in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All query strings in viewer requests are included in the cache key and in requests that CloudFront sends to the origin, **except** those that are listed in the `QueryStringNames` type, which are not included.\n- `all` \u2013 All query strings in viewer requests are included in the cache key and in requests that CloudFront sends to the origin.", "QueryStrings": "Contains a list of query string names." } }, @@ -8257,7 +8265,7 @@ "attributes": {}, "description": "An object that determines whether any cookies in viewer requests (and if so, which cookies) are included in requests that CloudFront sends to the origin.", "properties": { - "CookieBehavior": "Determines whether cookies in viewer requests are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 Cookies in viewer requests are not included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any cookies that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 The cookies in viewer requests that are listed in the `CookieNames` type are included in requests that CloudFront sends to the origin.\n- `all` \u2013 All cookies in viewer requests are included in requests that CloudFront sends to the origin.", + "CookieBehavior": "Determines whether cookies in viewer requests are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No cookies in viewer requests are included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any cookies that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the cookies in viewer requests that are listed in the `CookieNames` type are included in requests that CloudFront sends to the origin.\n- `all` \u2013 All cookies in viewer requests are included in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All cookies in viewer requests are included in requests that CloudFront sends to the origin, **except** for those listed in the `CookieNames` type, which are not included.", "Cookies": "Contains a list of cookie names." } }, @@ -8265,7 +8273,7 @@ "attributes": {}, "description": "An object that determines whether any HTTP headers (and if so, which headers) are included in requests that CloudFront sends to the origin.", "properties": { - "HeaderBehavior": "Determines whether any HTTP headers are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 HTTP headers are not included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any headers that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 The HTTP headers that are listed in the `Headers` type are included in requests that CloudFront sends to the origin.\n- `allViewer` \u2013 All HTTP headers in viewer requests are included in requests that CloudFront sends to the origin.\n- `allViewerAndWhitelistCloudFront` \u2013 All HTTP headers in viewer requests and the additional CloudFront headers that are listed in the `Headers` type are included in requests that CloudFront sends to the origin. The additional headers are added by CloudFront.", + "HeaderBehavior": "Determines whether any HTTP headers are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No HTTP headers in viewer requests are included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any headers that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the HTTP headers that are listed in the `Headers` type are included in requests that CloudFront sends to the origin.\n- `allViewer` \u2013 All HTTP headers in viewer requests are included in requests that CloudFront sends to the origin.\n- `allViewerAndWhitelistCloudFront` \u2013 All HTTP headers in viewer requests and the additional CloudFront headers that are listed in the `Headers` type are included in requests that CloudFront sends to the origin. The additional headers are added by CloudFront.\n- `allExcept` \u2013 All HTTP headers in viewer requests are included in requests that CloudFront sends to the origin, **except** for those listed in the `Headers` type, which are not included.", "Headers": "Contains a list of HTTP header names." } }, @@ -8284,7 +8292,7 @@ "attributes": {}, "description": "An object that determines whether any URL query strings in viewer requests (and if so, which query strings) are included in requests that CloudFront sends to the origin.", "properties": { - "QueryStringBehavior": "Determines whether any URL query strings in viewer requests are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 Query strings in viewer requests are not included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any query strings that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 The query strings in viewer requests that are listed in the `QueryStringNames` type are included in requests that CloudFront sends to the origin.\n- `all` \u2013 All query strings in viewer requests are included in requests that CloudFront sends to the origin.", + "QueryStringBehavior": "Determines whether any URL query strings in viewer requests are included in requests that CloudFront sends to the origin. Valid values are:\n\n- `none` \u2013 No query strings in viewer requests are included in requests that CloudFront sends to the origin. Even when this field is set to `none` , any query strings that are listed in a `CachePolicy` *are* included in origin requests.\n- `whitelist` \u2013 Only the query strings in viewer requests that are listed in the `QueryStringNames` type are included in requests that CloudFront sends to the origin.\n- `all` \u2013 All query strings in viewer requests are included in requests that CloudFront sends to the origin.\n- `allExcept` \u2013 All query strings in viewer requests are included in requests that CloudFront sends to the origin, **except** for those listed in the `QueryStringNames` type, which are not included.", "QueryStrings": "Contains a list of query string names." } }, @@ -8556,26 +8564,16 @@ "AWS::CloudTrail::Channel": { "attributes": { "ChannelArn": "`Ref` returns the ARN of the CloudTrail channel, such as `arn:aws:cloudtrail:us-east-2:123456789012:channel/01234567890` .", - "Channels": "`Ref` returns the names of CloudTrail channels.", "Ref": "When the logical ID of this resource is provided to the Ref intrinsic function, `Ref` returns the resource name." }, "description": "Contains information about a returned CloudTrail channel.", "properties": { - "Channel": "Contains information about a returned CloudTrail channel.", "Destinations": "One or more event data stores to which events arriving through a channel will be logged.", "Name": "The name of the channel.", "Source": "The name of the partner or external event source. You cannot change this name after you create the channel. A maximum of one channel is allowed per source.\n\nA source can be either `Custom` for all valid non- AWS events, or the name of a partner event source. For information about the source names for available partners, see [Additional information about integration partners](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/query-event-data-store-integration.html#cloudtrail-lake-partner-information) in the CloudTrail User Guide.", "Tags": "A list of tags." } }, - "AWS::CloudTrail::Channel.Channel": { - "attributes": {}, - "description": "Contains information about a returned CloudTrail channel.", - "properties": { - "ChannelArn": "The Amazon Resource Name (ARN) of a channel.", - "Name": "The name of the CloudTrail channel. For service-linked channels, the name is `aws-service-channel/service-name/custom-suffix` where `service-name` represents the name of the AWS service that created the channel and `custom-suffix` represents the suffix created by the AWS service." - } - }, "AWS::CloudTrail::Channel.Destination": { "attributes": {}, "description": "Contains information about the destination receiving events.", @@ -8618,7 +8616,7 @@ "properties": { "EndsWith": "An operator that includes events that match the last few characters of the event record field specified as the value of `Field` .", "Equals": "An operator that includes events that match the exact value of the event record field specified as the value of `Field` . This is the only valid operator that you can use with the `readOnly` , `eventCategory` , and `resources.type` fields.", - "Field": "A field in a CloudTrail event record on which to filter events to be logged. For event data stores for AWS Config configuration items, Audit Manager evidence, or non- AWS events, the field is used only for selecting events as filtering is not supported.\n\nFor CloudTrail event records, supported fields include `readOnly` , `eventCategory` , `eventSource` (for management events), `eventName` , `resources.type` , and `resources.ARN` .\n\nFor event data stores for AWS Config configuration items, Audit Manager evidence, or non- AWS events, the only supported field is `eventCategory` .\n\n- *`readOnly`* - Optional. Can be set to `Equals` a value of `true` or `false` . If you do not add this field, CloudTrail logs both `read` and `write` events. A value of `true` logs only `read` events. A value of `false` logs only `write` events.\n- *`eventSource`* - For filtering management events only. This can be set only to `NotEquals` `kms.amazonaws.com` .\n- *`eventName`* - Can use any operator. You can use it to \ufb01lter in or \ufb01lter out any data event logged to CloudTrail, such as `PutBucket` or `GetSnapshotBlock` . You can have multiple values for this \ufb01eld, separated by commas.\n- *`eventCategory`* - This is required and must be set to `Equals` .\n\n- For CloudTrail event records, the value must be `Management` or `Data` .\n- For AWS Config configuration items, the value must be `ConfigurationItem` .\n- For Audit Manager evidence, the value must be `Evidence` .\n- For non- AWS events, the value must be `ActivityAuditLog` .\n- *`resources.type`* - This \ufb01eld is required for CloudTrail data events. `resources.type` can only use the `Equals` operator, and the value can be one of the following:\n\n- `AWS::DynamoDB::Table`\n- `AWS::Lambda::Function`\n- `AWS::S3::Object`\n- `AWS::CloudTrail::Channel`\n- `AWS::Cognito::IdentityPool`\n- `AWS::DynamoDB::Stream`\n- `AWS::EC2::Snapshot`\n- `AWS::FinSpace::Environment`\n- `AWS::Glue::Table`\n- `AWS::KendraRanking::ExecutionPlan`\n- `AWS::ManagedBlockchain::Node`\n- `AWS::SageMaker::ExperimentTrialComponent`\n- `AWS::SageMaker::FeatureGroup`\n- `AWS::S3::AccessPoint`\n- `AWS::S3ObjectLambda::AccessPoint`\n- `AWS::S3Outposts::Object`\n\nYou can have only one `resources.type` \ufb01eld per selector. To log data events on more than one resource type, add another selector.\n- *`resources.ARN`* - You can use any operator with `resources.ARN` , but if you use `Equals` or `NotEquals` , the value must exactly match the ARN of a valid resource of the type you've speci\ufb01ed in the template as the value of resources.type. For example, if resources.type equals `AWS::S3::Object` , the ARN must be in one of the following formats. To log all data events for all objects in a specific S3 bucket, use the `StartsWith` operator, and include only the bucket ARN as the matching value.\n\nThe trailing slash is intentional; do not exclude it. Replace the text between less than and greater than symbols (<>) with resource-specific information.\n\n- `arn::s3:::/`\n- `arn::s3::://`\n\nWhen resources.type equals `AWS::DynamoDB::Table` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::dynamodb:::table/`\n\nWhen resources.type equals `AWS::Lambda::Function` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::lambda:::function:`\n\nWhen resources.type equals `AWS::CloudTrail::Channel` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::cloudtrail:::channel/`\n\nWhen resources.type equals `AWS::Cognito::IdentityPool` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::cognito-identity:::identitypool/`\n\nWhen `resources.type` equals `AWS::DynamoDB::Stream` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::dynamodb:::table//stream/`\n\nWhen `resources.type` equals `AWS::EC2::Snapshot` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::ec2:::snapshot/`\n\nWhen `resources.type` equals `AWS::FinSpace::Environment` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::finspace:::environment/`\n\nWhen `resources.type` equals `AWS::Glue::Table` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::glue:::table//`\n\nWhen `resources.type` equals `AWS::KendraRanking::ExecutionPlan` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::kendra-ranking:::table//`\n\nWhen `resources.type` equals `AWS::ManagedBlockchain::Node` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::managedblockchain:::nodes/`\n\nWhen `resources.type` equals `AWS::SageMaker::ExperimentTrialComponent` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::sagemaker:::experiment-trial-component/`\n\nWhen `resources.type` equals `AWS::SageMaker::FeatureGroup` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::sagemaker:::feature-group/`\n\nWhen `resources.type` equals `AWS::S3::AccessPoint` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in one of the following formats. To log events on all objects in an S3 access point, we recommend that you use only the access point ARN, don\u2019t include the object path, and use the `StartsWith` or `NotStartsWith` operators.\n\n- `arn::s3:::accesspoint/`\n- `arn::s3:::accesspoint//object/`\n\nWhen `resources.type` equals `AWS::S3ObjectLambda::AccessPoint` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::s3-object-lambda:::accesspoint/`\n\nWhen `resources.type` equals `AWS::S3Outposts::Object` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::s3-outposts:::`", + "Field": "A field in a CloudTrail event record on which to filter events to be logged. For event data stores for AWS Config configuration items, Audit Manager evidence, or non- AWS events, the field is used only for selecting events as filtering is not supported.\n\nFor CloudTrail event records, supported fields include `readOnly` , `eventCategory` , `eventSource` (for management events), `eventName` , `resources.type` , and `resources.ARN` .\n\nFor event data stores for AWS Config configuration items, Audit Manager evidence, or non- AWS events, the only supported field is `eventCategory` .\n\n- *`readOnly`* - Optional. Can be set to `Equals` a value of `true` or `false` . If you do not add this field, CloudTrail logs both `read` and `write` events. A value of `true` logs only `read` events. A value of `false` logs only `write` events.\n- *`eventSource`* - For filtering management events only. This can be set only to `NotEquals` `kms.amazonaws.com` .\n- *`eventName`* - Can use any operator. You can use it to \ufb01lter in or \ufb01lter out any data event logged to CloudTrail, such as `PutBucket` or `GetSnapshotBlock` . You can have multiple values for this \ufb01eld, separated by commas.\n- *`eventCategory`* - This is required and must be set to `Equals` .\n\n- For CloudTrail event records, the value must be `Management` or `Data` .\n- For AWS Config configuration items, the value must be `ConfigurationItem` .\n- For Audit Manager evidence, the value must be `Evidence` .\n- For non- AWS events, the value must be `ActivityAuditLog` .\n- *`resources.type`* - This \ufb01eld is required for CloudTrail data events. `resources.type` can only use the `Equals` operator, and the value can be one of the following:\n\n- `AWS::DynamoDB::Table`\n- `AWS::Lambda::Function`\n- `AWS::S3::Object`\n- `AWS::CloudTrail::Channel`\n- `AWS::Cognito::IdentityPool`\n- `AWS::DynamoDB::Stream`\n- `AWS::EC2::InstanceConnectEndpoint`\n- `AWS::EC2::Snapshot`\n- `AWS::FinSpace::Environment`\n- `AWS::Glue::Table`\n- `AWS::KendraRanking::ExecutionPlan`\n- `AWS::ManagedBlockchain::Node`\n- `AWS::SageMaker::ExperimentTrialComponent`\n- `AWS::SageMaker::FeatureGroup`\n- `AWS::S3::AccessPoint`\n- `AWS::S3ObjectLambda::AccessPoint`\n- `AWS::S3Outposts::Object`\n\nYou can have only one `resources.type` \ufb01eld per selector. To log data events on more than one resource type, add another selector.\n- *`resources.ARN`* - You can use any operator with `resources.ARN` , but if you use `Equals` or `NotEquals` , the value must exactly match the ARN of a valid resource of the type you've speci\ufb01ed in the template as the value of resources.type. For example, if resources.type equals `AWS::S3::Object` , the ARN must be in one of the following formats. To log all data events for all objects in a specific S3 bucket, use the `StartsWith` operator, and include only the bucket ARN as the matching value.\n\nThe trailing slash is intentional; do not exclude it. Replace the text between less than and greater than symbols (<>) with resource-specific information.\n\n- `arn::s3:::/`\n- `arn::s3::://`\n\nWhen resources.type equals `AWS::DynamoDB::Table` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::dynamodb:::table/`\n\nWhen resources.type equals `AWS::Lambda::Function` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::lambda:::function:`\n\nWhen resources.type equals `AWS::CloudTrail::Channel` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::cloudtrail:::channel/`\n\nWhen resources.type equals `AWS::Cognito::IdentityPool` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::cognito-identity:::identitypool/`\n\nWhen `resources.type` equals `AWS::DynamoDB::Stream` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::dynamodb:::table//stream/`\n\nWhen `resources.type` equals `AWS::EC2::InstanceConnectEndpoint` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::ec2:::instance-connect-endpoint/`\n\nWhen `resources.type` equals `AWS::EC2::Snapshot` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::ec2:::snapshot/`\n\nWhen `resources.type` equals `AWS::FinSpace::Environment` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::finspace:::environment/`\n\nWhen `resources.type` equals `AWS::Glue::Table` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::glue:::table//`\n\nWhen `resources.type` equals `AWS::KendraRanking::ExecutionPlan` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::kendra-ranking:::table//`\n\nWhen `resources.type` equals `AWS::ManagedBlockchain::Node` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::managedblockchain:::nodes/`\n\nWhen `resources.type` equals `AWS::SageMaker::ExperimentTrialComponent` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::sagemaker:::experiment-trial-component/`\n\nWhen `resources.type` equals `AWS::SageMaker::FeatureGroup` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::sagemaker:::feature-group/`\n\nWhen `resources.type` equals `AWS::S3::AccessPoint` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in one of the following formats. To log events on all objects in an S3 access point, we recommend that you use only the access point ARN, don\u2019t include the object path, and use the `StartsWith` or `NotStartsWith` operators.\n\n- `arn::s3:::accesspoint/`\n- `arn::s3:::accesspoint//object/`\n\nWhen `resources.type` equals `AWS::S3ObjectLambda::AccessPoint` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::s3-object-lambda:::accesspoint/`\n\nWhen `resources.type` equals `AWS::S3Outposts::Object` , and the operator is set to `Equals` or `NotEquals` , the ARN must be in the following format:\n\n- `arn::s3-outposts:::`", "NotEndsWith": "An operator that excludes events that match the last few characters of the event record field specified as the value of `Field` .", "NotEquals": "An operator that excludes events that match the exact value of the event record field specified as the value of `Field` .", "NotStartsWith": "An operator that excludes events that match the first few characters of the event record field specified as the value of `Field` .", @@ -8648,7 +8646,7 @@ "EnableLogFileValidation": "Specifies whether log file validation is enabled. The default is false.\n\n> When you disable log file integrity validation, the chain of digest files is broken after one hour. CloudTrail does not create digest files for log files that were delivered during a period in which log file integrity validation was disabled. For example, if you enable log file integrity validation at noon on January 1, disable it at noon on January 2, and re-enable it at noon on January 10, digest files will not be created for the log files delivered from noon on January 2 to noon on January 10. The same applies whenever you stop CloudTrail logging or delete a trail.", "EventSelectors": "Use event selectors to further specify the management and data event settings for your trail. By default, trails created without specific event selectors will be configured to log all read and write management events, and no data events. When an event occurs in your account, CloudTrail evaluates the event selector for all trails. For each trail, if the event matches any event selector, the trail processes and logs the event. If the event doesn't match any event selector, the trail doesn't log the event.\n\nYou can configure up to five event selectors for a trail.", "IncludeGlobalServiceEvents": "Specifies whether the trail is publishing events from global services such as IAM to the log files.", - "InsightSelectors": "A JSON string that contains the insight types you want to log on a trail. `ApiCallRateInsight` and `ApiErrorRateInsight` are valid insight types.", + "InsightSelectors": "A JSON string that contains the insight types you want to log on a trail. `ApiCallRateInsight` and `ApiErrorRateInsight` are valid Insight types.\n\nThe `ApiCallRateInsight` Insights type analyzes write-only management API calls that are aggregated per minute against a baseline API call volume.\n\nThe `ApiErrorRateInsight` Insights type analyzes management API calls that result in error codes. The error is shown if the API call is unsuccessful.", "IsLogging": "Whether the CloudTrail trail is currently logging AWS API calls.", "IsMultiRegionTrail": "Specifies whether the trail applies only to the current region or to all regions. The default is false. If the trail exists only in the current region and this value is set to true, shadow trails (replications of the trail) will be created in the other regions. If the trail exists in all regions and this value is set to false, the trail will remain in the region where it was created, and its shadow trails in other regions will be deleted. As a best practice, consider using trails that log events in all regions.", "IsOrganizationTrail": "Specifies whether the trail is applied to all accounts in an organization in AWS Organizations , or only for the current AWS account . The default is false, and cannot be true unless the call is made on behalf of an AWS account that is the management account or delegated administrator account for an organization in AWS Organizations . If the trail is not an organization trail and this is set to `true` , the trail will be created in all AWS accounts that belong to the organization. If the trail is an organization trail and this is set to `false` , the trail will remain in the current AWS account but be deleted from all member accounts in the organization.", @@ -8680,9 +8678,9 @@ }, "AWS::CloudTrail::Trail.InsightSelector": { "attributes": {}, - "description": "A JSON string that contains a list of insight types that are logged on a trail.", + "description": "A JSON string that contains a list of Insights types that are logged on a trail.", "properties": { - "InsightType": "The type of insights to log on a trail. `ApiCallRateInsight` and `ApiErrorRateInsight` are valid insight types." + "InsightType": "The type of Insights events to log on a trail. `ApiCallRateInsight` and `ApiErrorRateInsight` are valid Insight types.\n\nThe `ApiCallRateInsight` Insights type analyzes write-only management API calls that are aggregated per minute against a baseline API call volume.\n\nThe `ApiErrorRateInsight` Insights type analyzes management API calls that result in error codes. The error is shown if the API call is unsuccessful." } }, "AWS::CloudWatch::Alarm": { @@ -12117,7 +12115,7 @@ "ReplicationInstancePrivateIpAddresses": "One or more private IP addresses for the replication instance.", "ReplicationInstancePublicIpAddresses": "One or more public IP addresses for the replication instance." }, - "description": "The `AWS::DMS::ReplicationInstance` resource creates an AWS DMS replication instance.", + "description": "The `AWS::DMS::ReplicationInstance` resource creates an AWS DMS replication instance. To create a ReplicationInstance, you need permissions to create instances. You'll need similar permissions to terminate instances when you delete stacks with instances.", "properties": { "AllocatedStorage": "The amount of storage (in gigabytes) to be initially allocated for the replication instance.", "AllowMajorVersionUpgrade": "Indicates that major version upgrades are allowed. Changing this parameter does not result in an outage, and the change is asynchronously applied as soon as possible.\n\nThis parameter must be set to `true` when specifying a value for the `EngineVersion` parameter that is a different major version than the replication instance's current version.", @@ -12948,7 +12946,7 @@ "attributes": {}, "description": "Specifies the version of the Server Message Block (SMB) protocol that AWS DataSync uses to access an SMB file server.", "properties": { - "Version": "By default, DataSync automatically chooses an SMB protocol version based on negotiation with your SMB file server. You also can configure DataSync to use a specific SMB version, but we recommend doing this only if DataSync has trouble negotiating with the SMB file server automatically.\n\nThese are the following options for configuring the SMB version:\n\n- `AUTOMATIC` (default): DataSync and the SMB file server negotiate a protocol version that they mutually support. (DataSync supports SMB versions 1.0 and later.)\n\nThis is the recommended option. If you instead choose a specific version that your file server doesn't support, you may get an `Operation Not Supported` error.\n- `SMB3` : Restricts the protocol negotiation to only SMB version 3.0.2.\n- `SMB2` : Restricts the protocol negotiation to only SMB version 2.1.\n- `SMB2_0` : Restricts the protocol negotiation to only SMB version 2.0.\n- `SMB1` : Restricts the protocol negotiation to only SMB version 1.0.\n\n> The `SMB1` option isn't available when [creating an Amazon FSx for NetApp ONTAP location](https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationFsxOntap.html) ." + "Version": "By default, DataSync automatically chooses an SMB protocol version based on negotiation with your SMB file server. You also can configure DataSync to use a specific SMB version, but we recommend doing this only if DataSync has trouble negotiating with the SMB file server automatically.\n\nThese are the following options for configuring the SMB version:\n\n- `AUTOMATIC` (default): DataSync and the SMB file server negotiate the highest version of SMB that they mutually support between 2.1 and 3.1.1.\n\nThis is the recommended option. If you instead choose a specific version that your file server doesn't support, you may get an `Operation Not Supported` error.\n- `SMB3` : Restricts the protocol negotiation to only SMB version 3.0.2.\n- `SMB2` : Restricts the protocol negotiation to only SMB version 2.1.\n- `SMB2_0` : Restricts the protocol negotiation to only SMB version 2.0.\n- `SMB1` : Restricts the protocol negotiation to only SMB version 1.0.\n\n> The `SMB1` option isn't available when [creating an Amazon FSx for NetApp ONTAP location](https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationFsxOntap.html) ." } }, "AWS::DataSync::LocationFSxOpenZFS": { @@ -13136,7 +13134,7 @@ "attributes": {}, "description": "Specifies the version of the SMB protocol that DataSync uses to access your SMB file server.", "properties": { - "Version": "By default, DataSync automatically chooses an SMB protocol version based on negotiation with your SMB file server. You also can configure DataSync to use a specific SMB version, but we recommend doing this only if DataSync has trouble negotiating with the SMB file server automatically.\n\nThese are the following options for configuring the SMB version:\n\n- `AUTOMATIC` (default): DataSync and the SMB file server negotiate a protocol version that they mutually support. (DataSync supports SMB versions 1.0 and later.)\n\nThis is the recommended option. If you instead choose a specific version that your file server doesn't support, you may get an `Operation Not Supported` error.\n- `SMB3` : Restricts the protocol negotiation to only SMB version 3.0.2.\n- `SMB2` : Restricts the protocol negotiation to only SMB version 2.1.\n- `SMB2_0` : Restricts the protocol negotiation to only SMB version 2.0.\n- `SMB1` : Restricts the protocol negotiation to only SMB version 1.0.\n\n> The `SMB1` option isn't available when [creating an Amazon FSx for NetApp ONTAP location](https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationFsxOntap.html) ." + "Version": "By default, DataSync automatically chooses an SMB protocol version based on negotiation with your SMB file server. You also can configure DataSync to use a specific SMB version, but we recommend doing this only if DataSync has trouble negotiating with the SMB file server automatically.\n\nThese are the following options for configuring the SMB version:\n\n- `AUTOMATIC` (default): DataSync and the SMB file server negotiate the highest version of SMB that they mutually support between 2.1 and 3.1.1.\n\nThis is the recommended option. If you instead choose a specific version that your file server doesn't support, you may get an `Operation Not Supported` error.\n- `SMB3` : Restricts the protocol negotiation to only SMB version 3.0.2.\n- `SMB2` : Restricts the protocol negotiation to only SMB version 2.1.\n- `SMB2_0` : Restricts the protocol negotiation to only SMB version 2.0.\n- `SMB1` : Restricts the protocol negotiation to only SMB version 1.0.\n\n> The `SMB1` option isn't available when [creating an Amazon FSx for NetApp ONTAP location](https://docs.aws.amazon.com/datasync/latest/userguide/API_CreateLocationFsxOntap.html) ." } }, "AWS::DataSync::Task": { @@ -13224,7 +13222,7 @@ "Id": "The ID of the notification channel.", "Ref": "When the logical ID of this resource is provided to the `Ref` intrinsic function, `Ref` returns Amazon Resource Name (ARN) of the `NotificationChannel` . For more information about using the `Ref` function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) ." }, - "description": "Adds a notification channel to DevOps Guru. A notification channel is used to notify you about important DevOps Guru events, such as when an insight is generated.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for cross account Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. For more information, see Permissions for cross account Amazon SNS topics.\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) .", + "description": "Adds a notification channel to DevOps Guru. A notification channel is used to notify you about important DevOps Guru events, such as when an insight is generated.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to send it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) .", "properties": { "Config": "A `NotificationChannelConfig` object that contains information about configured notification channels." } @@ -13234,7 +13232,7 @@ "description": "Information about notification channels you have configured with DevOps Guru. The one supported notification channel is Amazon Simple Notification Service (Amazon SNS).", "properties": { "Filters": "The filter configurations for the Amazon SNS notification topic you use with DevOps Guru. If you do not provide filter configurations, the default configurations are to receive notifications for all message types of `High` or `Medium` severity.", - "Sns": "Information about a notification channel configured in DevOps Guru to send notifications when insights are created.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for cross account Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. For more information, see Permissions for cross account Amazon SNS topics.\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) ." + "Sns": "Information about a notification channel configured in DevOps Guru to send notifications when insights are created.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to send it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) ." } }, "AWS::DevOpsGuru::NotificationChannel.NotificationFilterConfig": { @@ -13247,7 +13245,7 @@ }, "AWS::DevOpsGuru::NotificationChannel.SnsChannelConfig": { "attributes": {}, - "description": "Contains the Amazon Resource Name (ARN) of an Amazon Simple Notification Service topic.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for cross account Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. For more information, see Permissions for cross account Amazon SNS topics.\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) .", + "description": "Contains the Amazon Resource Name (ARN) of an Amazon Simple Notification Service topic.\n\nIf you use an Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru permission to send it notifications. DevOps Guru adds the required policy on your behalf to send notifications using Amazon SNS in your account. DevOps Guru only supports standard SNS topics. For more information, see [Permissions for Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-required-permissions.html) .\n\nIf you use an Amazon SNS topic that is encrypted by an AWS Key Management Service customer-managed key (CMK), then you must add permissions to the CMK. For more information, see [Permissions for AWS KMS\u2013encrypted Amazon SNS topics](https://docs.aws.amazon.com/devops-guru/latest/userguide/sns-kms-permissions.html) .", "properties": { "TopicArn": "The Amazon Resource Name (ARN) of an Amazon Simple Notification Service topic." } @@ -14185,7 +14183,7 @@ "properties": { "AvailabilityZone": "The Availability Zone in which to launch the instances.", "InstanceRequirements": "The attributes for the instance types. When you specify instance attributes, Amazon EC2 will identify instance types with those attributes.\n\n> If you specify `InstanceRequirements` , you can't specify `InstanceType` .", - "InstanceType": "The instance type.\n\n> If you specify `InstanceType` , you can't specify `InstanceRequirements` .", + "InstanceType": "The instance type.\n\n`mac1.metal` is not supported as a launch template override.\n\n> If you specify `InstanceType` , you can't specify `InstanceRequirements` .", "MaxPrice": "The maximum price per unit hour that you are willing to pay for a Spot Instance. We do not recommend using this parameter because it can lead to increased interruptions. If you do not specify this parameter, you will pay the current Spot price.\n\n> If you specify a maximum price, your instances will be interrupted more frequently than if you do not specify this parameter.", "Placement": "The location where the instance launched, if applicable.", "Priority": "The priority for the launch template override. The highest priority is launched first.\n\nIf the On-Demand `AllocationStrategy` is set to `prioritized` , EC2 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 `capacity-optimized-prioritized` , EC2 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.", @@ -16675,7 +16673,8 @@ }, "AWS::EC2::VPCEndpointService": { "attributes": { - "Ref": "`Ref` returns the ID of the VPC endpoint service configuration." + "Ref": "`Ref` returns the ID of the VPC endpoint service configuration.", + "ServiceId": "" }, "description": "Creates a VPC endpoint service configuration to which service consumers ( AWS accounts, 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": { @@ -17751,7 +17750,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` .", "Id": "The ID of your local Amazon EKS cluster on an AWS Outpost. This property isn't available for an Amazon EKS cluster on the AWS cloud.", - "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.", + "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.", "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." }, @@ -17764,7 +17763,7 @@ "OutpostConfig": "An object representing the configuration of your local Amazon EKS cluster on an AWS Outpost. This object isn't available for clusters on the AWS cloud.", "ResourcesVpcConfig": "The VPC configuration that's used by the cluster control plane. Amazon EKS VPC resources have specific requirements to work properly with Kubernetes. For more information, see [Cluster VPC Considerations](https://docs.aws.amazon.com/eks/latest/userguide/network_reqs.html) and [Cluster Security Group Considerations](https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html) in the *Amazon EKS User Guide* . You must specify at least two subnets. You can specify up to five security groups, but we recommend that you use a dedicated security group for your cluster control plane.\n\n> Updates require replacement of the `SecurityGroupIds` and `SubnetIds` sub-properties.", "RoleArn": "The Amazon Resource Name (ARN) of the IAM role that provides permissions for the Kubernetes control plane to make calls to AWS API operations on your behalf. For more information, see [Amazon EKS Service IAM Role](https://docs.aws.amazon.com/eks/latest/userguide/service_IAM_role.html) in the **Amazon EKS User Guide** .", - "Tags": "The metadata that you apply to the cluster to assist with categorization and organization. Each tag consists of a key and an optional value, both of which you define. Cluster tags don't propagate to any other resources associated with the cluster.\n\n> You must have the `eks:TagResource` and `eks:UntagResource` permissions in your IAM user or IAM role used to manage the CloudFormation stack. If you don't have these permissions, there might be unexpected behavior with stack-level tags propagating to the resource during resource creation and update.", + "Tags": "The metadata that you apply to the cluster to assist with categorization and organization. Each tag consists of a key and an optional value, both of which you define. Cluster tags don't propagate to any other resources associated with the cluster.\n\n> You must have the `eks:TagResource` and `eks:UntagResource` permissions for your [IAM principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html) to manage the AWS CloudFormation stack. If you don't have these permissions, there might be unexpected behavior with stack-level tags propagating to the resource during resource creation and update.", "Version": "The desired Kubernetes version for your cluster. If you don't specify a value here, the default version available in Amazon EKS is used.\n\n> The default version might not be the latest version available." } }, @@ -19613,7 +19612,7 @@ "HealthCheckPort": "The port the load balancer uses when performing health checks on targets. If the protocol is HTTP, HTTPS, TCP, TLS, UDP, or TCP_UDP, the default is `traffic-port` , which is the port on which each target receives traffic from the load balancer. If the protocol is GENEVE, the default is port 80.", "HealthCheckProtocol": "The protocol the load balancer uses when performing health checks on targets. For Application Load Balancers, the default is HTTP. For Network Load Balancers and Gateway Load Balancers, the default is TCP. The TCP protocol is not supported for health checks if the protocol of the target group is HTTP or HTTPS. The GENEVE, TLS, UDP, and TCP_UDP protocols are not supported for health checks.", "HealthCheckTimeoutSeconds": "The amount of time, in seconds, during which no response from a target means a failed health check. The range is 2\u2013120 seconds. For target groups with a protocol of HTTP, the default is 6 seconds. For target groups with a protocol of TCP, TLS or HTTPS, the default is 10 seconds. For target groups with a protocol of GENEVE, the default is 5 seconds. If the target type is `lambda` , the default is 30 seconds.", - "HealthyThresholdCount": "The number of consecutive health check successes required before considering a target healthy. The range is 2-10. If the target group protocol is TCP, TCP_UDP, UDP, TLS, HTTP or HTTPS, the default is 5. For target groups with a protocol of GENEVE, the default is 5. If the target type is `lambda` , the default is 5.", + "HealthyThresholdCount": "The number of consecutive health check successes required before considering a target healthy. The range is 2-10. If the target group protocol is TCP, TCP_UDP, UDP, TLS, HTTP or HTTPS, the default is 5. For target groups with a protocol of GENEVE, the default is 3. If the target type is `lambda` , the default is 5.", "IpAddressType": "The type of IP address used for this target group. The possible values are `ipv4` and `ipv6` . This is an optional parameter. If not specified, the IP address type defaults to `ipv4` .", "Matcher": "[HTTP/HTTPS health checks] The HTTP or gRPC codes to use when checking for a successful response from a target. For target groups with a protocol of TCP, TCP_UDP, UDP or TLS the range is 200-599. For target groups with a protocol of HTTP or HTTPS, the range is 200-499. For target groups with a protocol of GENEVE, the range is 200-399.", "Name": "The name of the target group.\n\nThis name must be unique per region per account, can have a maximum of 32 characters, must contain only alphanumeric characters or hyphens, and must not begin or end with a hyphen.", @@ -19624,7 +19623,7 @@ "TargetGroupAttributes": "The attributes.", "TargetType": "The type of target that you must specify when registering targets with this target group. You can't specify targets for a target group using more than one target type.\n\n- `instance` - Register targets by instance ID. This is the default value.\n- `ip` - Register targets by IP address. You can specify IP addresses from the subnets of the virtual private cloud (VPC) for the target group, the RFC 1918 range (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and the RFC 6598 range (100.64.0.0/10). You can't specify publicly routable IP addresses.\n- `lambda` - Register a single Lambda function as a target.\n- `alb` - Register a single Application Load Balancer as a target.", "Targets": "The targets.", - "UnhealthyThresholdCount": "The number of consecutive health check failures required before considering a target unhealthy. The range is 2-10. If the target group protocol is TCP, TCP_UDP, UDP, TLS, HTTP or HTTPS, the default is 2. For target groups with a protocol of GENEVE, the default is 2. If the target type is `lambda` , the default is 5.", + "UnhealthyThresholdCount": "The number of consecutive health check failures required before considering a target unhealthy. The range is 2-10. If the target group protocol is TCP, TCP_UDP, UDP, TLS, HTTP or HTTPS, the default is 2. For target groups with a protocol of GENEVE, the default is 3. If the target type is `lambda` , the default is 5.", "VpcId": "The identifier of the virtual private cloud (VPC). If the target is a Lambda function, this parameter does not apply. Otherwise, this parameter is required." } }, @@ -23458,7 +23457,7 @@ "DeploymentId": "The ID of the deployment.", "Ref": "`Ref` returns the `DeploymentId` ." }, - "description": "Creates a continuous deployment for a target, which is a AWS IoT Greengrass core device or group of core devices. When you add a new core device to a group of core devices that has a deployment, AWS IoT Greengrass deploys that group's deployment to the new device.\n\nYou can define one deployment for each target. When you create a new deployment for a target that has an existing deployment, you replace the previous deployment. AWS IoT Greengrass applies the new deployment to the target devices.\n\nYou can only add, update, or delete up to 10 deployments at a time to a single target.\n\nEvery deployment has a revision number that indicates how many deployment revisions you define for a target. Use this operation to create a new revision of an existing deployment. This operation returns the revision number of the new deployment when you create it.\n\nFor more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/latest/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .\n\n> Deployment resources are deleted when you delete stacks. To keep the deployments in a stack, you must specify `\"DeletionPolicy\": \"Retain\"` on each deployment resource in the stack template that you want to keep. For more information, see [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) .\n> \n> You can only delete up to 10 deployment resources at a time. If you delete more than 10 resources, you receive an error.", + "description": "Creates a continuous deployment for a target, which is a AWS IoT Greengrass core device or group of core devices. When you add a new core device to a group of core devices that has a deployment, AWS IoT Greengrass deploys that group's deployment to the new device.\n\nYou can define one deployment for each target. When you create a new deployment for a target that has an existing deployment, you replace the previous deployment. AWS IoT Greengrass applies the new deployment to the target devices.\n\nYou can only add, update, or delete up to 10 deployments at a time to a single target.\n\nEvery deployment has a revision number that indicates how many deployment revisions you define for a target. Use this operation to create a new revision of an existing deployment. This operation returns the revision number of the new deployment when you create it.\n\nFor more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .\n\n> Deployment resources are deleted when you delete stacks. To keep the deployments in a stack, you must specify `\"DeletionPolicy\": \"Retain\"` on each deployment resource in the stack template that you want to keep. For more information, see [DeletionPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-deletionpolicy.html) .\n> \n> You can only delete up to 10 deployment resources at a time. If you delete more than 10 resources, you receive an error.", "properties": { "Components": "The components to deploy. This is a dictionary, where each key is the name of a component, and each key's value is the version and configuration to deploy for that component.", "DeploymentName": "The name of the deployment.", @@ -23498,13 +23497,13 @@ "attributes": {}, "description": "Contains information about a deployment's policy that defines when components are safe to update.\n\nEach component on a device can report whether or not it's ready to update. After a component and its dependencies are ready, they can apply the update in the deployment. You can configure whether or not the deployment notifies components of an update and waits for a response. You specify the amount of time each component has to respond to the update notification.", "properties": { - "Action": "Whether or not to notify components and wait for components to become safe to update. Choose from the following options:\n\n- `NOTIFY_COMPONENTS` \u2013 The deployment notifies each component before it stops and updates that component. Components can use the [SubscribeToComponentUpdates](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-subscribetocomponentupdates) IPC operation to receive these notifications. Then, components can respond with the [DeferComponentUpdate](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-defercomponentupdate) IPC operation. For more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/latest/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .\n- `SKIP_NOTIFY_COMPONENTS` \u2013 The deployment doesn't notify components or wait for them to be safe to update.\n\nDefault: `NOTIFY_COMPONENTS`", + "Action": "Whether or not to notify components and wait for components to become safe to update. Choose from the following options:\n\n- `NOTIFY_COMPONENTS` \u2013 The deployment notifies each component before it stops and updates that component. Components can use the [SubscribeToComponentUpdates](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-subscribetocomponentupdates) IPC operation to receive these notifications. Then, components can respond with the [DeferComponentUpdate](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-defercomponentupdate) IPC operation. For more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .\n- `SKIP_NOTIFY_COMPONENTS` \u2013 The deployment doesn't notify components or wait for them to be safe to update.\n\nDefault: `NOTIFY_COMPONENTS`", "TimeoutInSeconds": "The amount of time in seconds that each component on a device has to report that it's safe to update. If the component waits for longer than this timeout, then the deployment proceeds on the device.\n\nDefault: `60`" } }, "AWS::GreengrassV2::Deployment.DeploymentConfigurationValidationPolicy": { "attributes": {}, - "description": "Contains information about how long a component on a core device can validate its configuration updates before it times out. Components can use the [SubscribeToValidateConfigurationUpdates](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-subscribetovalidateconfigurationupdates) IPC operation to receive notifications when a deployment specifies a configuration update. Then, components can respond with the [SendConfigurationValidityReport](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-sendconfigurationvalidityreport) IPC operation. For more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/latest/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .", + "description": "Contains information about how long a component on a core device can validate its configuration updates before it times out. Components can use the [SubscribeToValidateConfigurationUpdates](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-subscribetovalidateconfigurationupdates) IPC operation to receive notifications when a deployment specifies a configuration update. Then, components can respond with the [SendConfigurationValidityReport](https://docs.aws.amazon.com/greengrass/v2/developerguide/interprocess-communication.html#ipc-operation-sendconfigurationvalidityreport) IPC operation. For more information, see the [Create deployments](https://docs.aws.amazon.com/greengrass/v2/developerguide/create-deployments.html) in the *AWS IoT Greengrass V2 Developer Guide* .", "properties": { "TimeoutInSeconds": "The amount of time in seconds that a component can validate its configuration updates. If the validation time exceeds this timeout, then the deployment proceeds for the device.\n\nDefault: `30`" } @@ -23860,7 +23859,7 @@ "description": "The `AWS::GuardDuty::Filter` resource specifies a new filter defined by the provided `findingCriteria` .", "properties": { "Action": "Specifies the action that is to be applied to the findings that match the filter.", - "Description": "The description of the filter. Valid characters include alphanumeric characters, and special characters such as `-` , `.` , `:` , `{ }` , `[ ]` , `( )` , `/` , `\\t` , `\\n` , `\\x0B` , `\\f` , `\\r` , `_` , and whitespace.", + "Description": "The description of the filter. Valid characters include alphanumeric characters, and special characters such as hyphen, period, colon, underscore, parentheses ( `{ }` , `[ ]` , and `( )` ), forward slash, horizontal tab, vertical tab, newline, form feed, return, and whitespace.", "DetectorId": "The ID of the detector belonging to the GuardDuty account that you want to create a filter for.", "FindingCriteria": "Represents the criteria to be used in the filter for querying findings.", "Name": "The name of the filter. Valid characters include period (.), underscore (_), dash (-), and alphanumeric characters. A whitespace is considered to be an invalid character.", @@ -30661,7 +30660,7 @@ }, "description": "The `AWS::Lambda::EventInvokeConfig` resource configures options for [asynchronous invocation](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html) on a version or an alias.\n\nBy default, Lambda retries an asynchronous invocation twice if the function returns an error. It retains events in a queue for up to six hours. When an event fails all processing attempts or stays in the asynchronous invocation queue for too long, Lambda discards it.", "properties": { - "DestinationConfig": "A destination for events after they have been sent to a function for processing.\n\n**Destinations** - *Function* - The Amazon Resource Name (ARN) of a Lambda function.\n- *Queue* - The ARN of an SQS queue.\n- *Topic* - The ARN of an SNS topic.\n- *Event Bus* - The ARN of an Amazon EventBridge event bus.", + "DestinationConfig": "A destination for events after they have been sent to a function for processing.\n\n**Destinations** - *Function* - The Amazon Resource Name (ARN) of a Lambda function.\n- *Queue* - The ARN of a standard SQS queue.\n- *Topic* - The ARN of a standard SNS topic.\n- *Event Bus* - The ARN of an Amazon EventBridge event bus.", "FunctionName": "The name of the Lambda function.\n\n*Minimum* : `1`\n\n*Maximum* : `64`\n\n*Pattern* : `([a-zA-Z0-9-_]+)`", "MaximumEventAgeInSeconds": "The maximum age of a request that Lambda sends to a function for processing.", "MaximumRetryAttempts": "The maximum number of times to retry when the function returns an error.", @@ -30698,11 +30697,11 @@ "description": "The `AWS::Lambda::EventSourceMapping` resource creates a mapping between an event source and an AWS Lambda function. Lambda reads items from the event source and triggers the function.\n\nFor details about each event source type, see the following topics. In particular, each of the topics describes the required and optional parameters for the specific event source.\n\n- [Configuring a Dynamo DB stream as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-dynamodb-eventsourcemapping)\n- [Configuring a Kinesis stream as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-eventsourcemapping)\n- [Configuring an SQS queue as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#events-sqs-eventsource)\n- [Configuring an MQ broker as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html#services-mq-eventsourcemapping)\n- [Configuring MSK as an event source](https://docs.aws.amazon.com/lambda/latest/dg/with-msk.html)\n- [Configuring Self-Managed Apache Kafka as an event source](https://docs.aws.amazon.com/lambda/latest/dg/kafka-smaa.html)", "properties": { "AmazonManagedKafkaEventSourceConfig": "Specific configuration settings for an Amazon Managed Streaming for Apache Kafka (Amazon MSK) event source.", - "BatchSize": "The maximum number of records in each batch that Lambda pulls from your stream or queue and sends to your function. Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB).\n\n- *Amazon Kinesis* \u2013 Default 100. Max 10,000.\n- *Amazon DynamoDB Streams* \u2013 Default 100. Max 10,000.\n- *Amazon Simple Queue Service* \u2013 Default 10. For standard queues the max is 10,000. For FIFO queues the max is 10.\n- *Amazon Managed Streaming for Apache Kafka* \u2013 Default 100. Max 10,000.\n- *Self-managed Apache Kafka* \u2013 Default 100. Max 10,000.\n- *Amazon MQ (ActiveMQ and RabbitMQ)* \u2013 Default 100. Max 10,000.", + "BatchSize": "The maximum number of records in each batch that Lambda pulls from your stream or queue and sends to your function. Lambda passes all of the records in the batch to the function in a single call, up to the payload limit for synchronous invocation (6 MB).\n\n- *Amazon Kinesis* \u2013 Default 100. Max 10,000.\n- *Amazon DynamoDB Streams* \u2013 Default 100. Max 10,000.\n- *Amazon Simple Queue Service* \u2013 Default 10. For standard queues the max is 10,000. For FIFO queues the max is 10.\n- *Amazon Managed Streaming for Apache Kafka* \u2013 Default 100. Max 10,000.\n- *Self-managed Apache Kafka* \u2013 Default 100. Max 10,000.\n- *Amazon MQ (ActiveMQ and RabbitMQ)* \u2013 Default 100. Max 10,000.\n- *DocumentDB* \u2013 Default 100. Max 10,000.", "BisectBatchOnFunctionError": "(Streams only) If the function returns an error, split the batch in two and retry. The default value is false.", "DestinationConfig": "(Streams only) An Amazon SQS queue or Amazon SNS topic destination for discarded records.", "Enabled": "When true, the event source mapping is active. When false, Lambda pauses polling and invocation.\n\nDefault: True", - "EventSourceArn": "The Amazon Resource Name (ARN) of the event source.\n\n- *Amazon Kinesis* \u2013 The ARN of the data stream or a stream consumer.\n- *Amazon DynamoDB Streams* \u2013 The ARN of the stream.\n- *Amazon Simple Queue Service* \u2013 The ARN of the queue.\n- *Amazon Managed Streaming for Apache Kafka* \u2013 The ARN of the cluster.\n- *Amazon MQ* \u2013 The ARN of the broker.", + "EventSourceArn": "The Amazon Resource Name (ARN) of the event source.\n\n- *Amazon Kinesis* \u2013 The ARN of the data stream or a stream consumer.\n- *Amazon DynamoDB Streams* \u2013 The ARN of the stream.\n- *Amazon Simple Queue Service* \u2013 The ARN of the queue.\n- *Amazon Managed Streaming for Apache Kafka* \u2013 The ARN of the cluster.\n- *Amazon MQ* \u2013 The ARN of the broker.\n- *Amazon DocumentDB* \u2013 The ARN of the DocumentDB change stream.", "FilterCriteria": "An object that defines the filter criteria that determine whether Lambda should process an event. For more information, see [Lambda event filtering](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) .", "FunctionName": "The name of the Lambda function.\n\n**Name formats** - *Function name* \u2013 `MyFunction` .\n- *Function ARN* \u2013 `arn:aws:lambda:us-west-2:123456789012:function:MyFunction` .\n- *Version or Alias ARN* \u2013 `arn:aws:lambda:us-west-2:123456789012:function:MyFunction:PROD` .\n- *Partial ARN* \u2013 `123456789012:function:MyFunction` .\n\nThe length constraint applies only to the full ARN. If you specify only the function name, it's limited to 64 characters in length.", "FunctionResponseTypes": "(Streams and SQS) A list of current response type enums applied to the event source mapping.\n\nValid Values: `ReportBatchItemFailures`", @@ -30800,7 +30799,7 @@ "SnapStartResponse.ApplyOn": "", "SnapStartResponse.OptimizationStatus": "" }, - "description": "The `AWS::Lambda::Function` resource creates a Lambda function. To create a function, you need a [deployment package](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html) and an [execution role](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html) . The deployment package is a .zip file archive or container image that contains your function code. The execution role grants the function permission to use AWS services, such as Amazon CloudWatch Logs for log streaming and AWS X-Ray for request tracing.\n\nYou set the package type to `Image` if the deployment package is a [container image](https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html) . For a container image, the code property must include the URI of a container image in the Amazon ECR registry. You do not need to specify the handler and runtime properties.\n\nYou set the package type to `Zip` if the deployment package is a [.zip file archive](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html#gettingstarted-package-zip) . For a .zip file archive, the code property specifies the location of the .zip file. You must also specify the handler and runtime properties. For a Python example, see [Deploy Python Lambda functions with .zip file archives](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html) .\n\nYou can use [code signing](https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html) if your deployment package is a .zip file archive. To enable code signing for this function, specify the ARN of a code-signing configuration. When a user attempts to deploy a code package with `UpdateFunctionCode` , Lambda checks that the code package has a valid signature from a trusted publisher. The code-signing configuration includes a set of signing profiles, which define the trusted publishers for this function.\n\nNote that you configure [provisioned concurrency](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html) on a `AWS::Lambda::Version` or a `AWS::Lambda::Alias` .\n\nFor a complete introduction to Lambda functions, see [What is Lambda?](https://docs.aws.amazon.com/lambda/latest/dg/lambda-welcome.html) in the *Lambda developer guide.*", + "description": "The `AWS::Lambda::Function` resource creates a Lambda function. To create a function, you need a [deployment package](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html) and an [execution role](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html) . The deployment package is a .zip file archive or container image that contains your function code. The execution role grants the function permission to use AWS services, such as Amazon CloudWatch Logs for log streaming and AWS X-Ray for request tracing.\n\nYou set the package type to `Image` if the deployment package is a [container image](https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html) . For a container image, the code property must include the URI of a container image in the Amazon ECR registry. You do not need to specify the handler and runtime properties.\n\nYou set the package type to `Zip` if the deployment package is a [.zip file archive](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-package.html#gettingstarted-package-zip) . For a .zip file archive, the code property specifies the location of the .zip file. You must also specify the handler and runtime properties. For a Python example, see [Deploy Python Lambda functions with .zip file archives](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html) .\n\nYou can use [code signing](https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html) if your deployment package is a .zip file archive. To enable code signing for this function, specify the ARN of a code-signing configuration. When a user attempts to deploy a code package with `UpdateFunctionCode` , Lambda checks that the code package has a valid signature from a trusted publisher. The code-signing configuration includes a set of signing profiles, which define the trusted publishers for this function.\n\nNote that you configure [provisioned concurrency](https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html) on a `AWS::Lambda::Version` or a `AWS::Lambda::Alias` .\n\nFor a complete introduction to Lambda functions, see [What is Lambda?](https://docs.aws.amazon.com/lambda/latest/dg/lambda-welcome.html) in the *Lambda developer guide.*", "properties": { "Architectures": "The instruction set architecture that the function supports. Enter a string array with one of the valid values (arm64 or x86_64). The default value is `x86_64` .", "Code": "The code for the function.", @@ -30882,7 +30881,7 @@ "description": "Sets the runtime management configuration for a function's version. For more information, see [Runtime updates](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html) .", "properties": { "RuntimeVersionArn": "The ARN of the runtime version you want the function to use.\n\n> This is only required if you're using the *Manual* runtime update mode.", - "UpdateRuntimeOn": "Specify the runtime update mode.\n\n- *Auto (default)* - Automatically update to the most recent and secure runtime version using a [Two-phase runtime version rollout](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html#runtime-management-two-phase) . This is the best choice for most customers to ensure they always benefit from runtime updates.\n- *Function update* - Lambda updates the runtime of you function to the most recent and secure runtime version when you update your function. This approach synchronizes runtime updates with function deployments, giving you control over when runtime updates are applied and allowing you to detect and mitigate rare runtime update incompatibilities early. When using this setting, you need to regularly update your functions to keep their runtime up-to-date.\n- *Manual* - You specify a runtime version in your function configuration. The function will use this runtime version indefinitely. In the rare case where a new runtime version is incompatible with an existing function, this allows you to roll back your function to an earlier runtime version. For more information, see [Roll back a runtime version](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html#runtime-management-rollback) .\n\n*Valid Values* : `Auto` | `Function update` | `Manual`" + "UpdateRuntimeOn": "Specify the runtime update mode.\n\n- *Auto (default)* - Automatically update to the most recent and secure runtime version using a [Two-phase runtime version rollout](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html#runtime-management-two-phase) . This is the best choice for most customers to ensure they always benefit from runtime updates.\n- *FunctionUpdate* - Lambda updates the runtime of you function to the most recent and secure runtime version when you update your function. This approach synchronizes runtime updates with function deployments, giving you control over when runtime updates are applied and allowing you to detect and mitigate rare runtime update incompatibilities early. When using this setting, you need to regularly update your functions to keep their runtime up-to-date.\n- *Manual* - You specify a runtime version in your function configuration. The function will use this runtime version indefinitely. In the rare case where a new runtime version is incompatible with an existing function, this allows you to roll back your function to an earlier runtime version. For more information, see [Roll back a runtime version](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html#runtime-management-rollback) .\n\n*Valid Values* : `Auto` | `FunctionUpdate` | `Manual`" } }, "AWS::Lambda::Function.SnapStart": { @@ -33556,9 +33555,9 @@ }, "AWS::ManagedBlockchain::Member.MemberFabricConfiguration": { "attributes": {}, - "description": "Configuration properties for Hyperledger Fabric for a member in a Managed Blockchain network using the Hyperledger Fabric framework.", + "description": "Configuration properties for Hyperledger Fabric for a member in a Managed Blockchain network that is using the Hyperledger Fabric framework.", "properties": { - "AdminPassword": "The password for the member's initial administrative user. The `AdminPassword` must be at least eight characters long and no more than 32 characters. It must contain at least one uppercase letter, one lowercase letter, and one digit. It cannot have a single quotation mark (\u2018), a double quotation marks (\u201c), a forward slash(/), a backward slash(\\), @, or a space.", + "AdminPassword": "The password for the member's initial administrative user. The `AdminPassword` must be at least 8 characters long and no more than 32 characters. It must contain at least one uppercase letter, one lowercase letter, and one digit. It cannot have a single quotation mark (\u2018), a double quotation marks (\u201c), a forward slash(/), a backward slash(\\), @, or a space.", "AdminUsername": "The user name for the member's initial administrative user." } }, @@ -33578,21 +33577,21 @@ "FrameworkVersion": "The version of the blockchain framework that the network uses.", "Name": "The name of the network.", "NetworkFrameworkConfiguration": "Configuration properties relevant to the network for the blockchain framework that the network uses.", - "VotingPolicy": "The voting rules for the network to decide if a proposal is accepted." + "VotingPolicy": "The voting rules that the network uses to decide if a proposal is accepted." } }, "AWS::ManagedBlockchain::Member.NetworkFabricConfiguration": { "attributes": {}, "description": "Hyperledger Fabric configuration properties for the network.", "properties": { - "Edition": "The edition of Amazon Managed Blockchain that the network uses. Valid values are `standard` and `starter` . For more information, see" + "Edition": "The edition of Amazon Managed Blockchain that the network uses. Valid values are `standard` and `starter` . For more information, see [Amazon Managed Blockchain Pricing](https://docs.aws.amazon.com/managed-blockchain/pricing/)" } }, "AWS::ManagedBlockchain::Member.NetworkFrameworkConfiguration": { "attributes": {}, "description": "Configuration properties relevant to the network for the blockchain framework that the network uses.", "properties": { - "NetworkFabricConfiguration": "Configuration properties for Hyperledger Fabric for a member in a Managed Blockchain network using the Hyperledger Fabric framework." + "NetworkFabricConfiguration": "Configuration properties for Hyperledger Fabric for a member in a Managed Blockchain network that is using the Hyperledger Fabric framework." } }, "AWS::ManagedBlockchain::Member.VotingPolicy": { @@ -36934,6 +36933,39 @@ "TransitGatewayArn": "The Amazon Resource Name (ARN) of the transit gateway." } }, + "AWS::NetworkManager::TransitGatewayRouteTableAttachment": { + "attributes": { + "AttachmentId": "The ID of the transit gateway route table attachment.", + "AttachmentPolicyRuleNumber": "The policy rule number associated with the attachment.", + "AttachmentType": "The type of attachment. This will be `TRANSIT_GATEWAY_ROUTE_TABLE` .", + "CoreNetworkArn": "The ARN of the core network.", + "CoreNetworkId": "The ID of the core network.", + "CreatedAt": "The timestamp when the transit gateway route table attachment was created.", + "EdgeLocation": "The Region where the core network edge is located.", + "OwnerAccountId": "The ID of the transit gateway route table attachment owner.", + "Ref": "`Ref` returns the attachment ID of the transit gateway route table. For example: `attachment-12367e74104d31234` .", + "ResourceArn": "The resource ARN for the transit gateway route table attachment.", + "SegmentName": "The name of the attachment's segment.", + "State": "The state of the attachment. This can be: `REJECTED` | `PENDING_ATTACHMENT_ACCEPTANCE` | `CREATING` | `FAILED` | `AVAILABLE` | `UPDATING` | `PENDING_NETWORK_UPDATE` | `PENDING_TAG_ACCEPTANCE` | `DELETING` .", + "UpdatedAt": "The timestamp when the transit gateway route table attachment was last updated." + }, + "description": "Creates a transit gateway route table attachment.", + "properties": { + "PeeringId": "The ID of the transit gateway peering.", + "ProposedSegmentChange": "This property is read-only. Values can't be assigned to it.", + "Tags": "The list of key-value pairs associated with the transit gateway route table attachment.", + "TransitGatewayRouteTableArn": "The ARN of the transit gateway attachment route table." + } + }, + "AWS::NetworkManager::TransitGatewayRouteTableAttachment.ProposedSegmentChange": { + "attributes": {}, + "description": "Describes a proposed segment change. In some cases, the segment change must first be evaluated and accepted.", + "properties": { + "AttachmentPolicyRuleNumber": "The rule number in the policy document that applies to this change.", + "SegmentName": "The name of the segment to change.", + "Tags": "The list of key-value tags that changed for the segment." + } + }, "AWS::NetworkManager::VpcAttachment": { "attributes": { "AttachmentId": "The ID of the VPC attachment.", @@ -38477,7 +38509,7 @@ "CustomDeliveryConfiguration": "The delivery configuration settings for sending the treatment through a custom channel. This object is required if the `MessageConfiguration` object for the treatment specifies a `CustomMessage` object.", "Description": "A custom description of the campaign.", "HoldoutPercent": "The allocated percentage of users (segment members) who shouldn't receive messages from the campaign.", - "IsPaused": "Specifies whether to pause the campaign. A paused campaign doesn't run unless you resume it by changing this value to `false` . If you restart a campaign, the campaign restarts from the beginning and not at the point you paused it.", + "IsPaused": "Specifies whether to pause the campaign. A paused campaign doesn't run unless you resume it by changing this value to `false` . If you restart a campaign, the campaign restarts from the beginning and not at the point you paused it. If a campaign is running it will complete and then pause. Pause only pauses or skips the next run for a recurring future scheduled campaign. A campaign scheduled for immediate can't be paused.", "Limits": "The messaging limits for the campaign.", "MessageConfiguration": "The message configuration settings for the campaign.", "Name": "The name of the campaign.", @@ -38717,7 +38749,7 @@ "description": "Specifies the name and version of the message template to use for the message.", "properties": { "Name": "The name of the message template to use for the message. If specified, this value must match the name of an existing message template.", - "Version": "The unique identifier for the version of the message template to use for the message. If specified, this value must match the identifier for an existing template version. To retrieve a list of versions and version identifiers for a template, use the Template Versions resource.\n\nIf you don't specify a value for this property, Amazon Pinpoint uses the *active version* of the template. The *active version* is typically the version of a template that's been most recently reviewed and approved for use, depending on your workflow. It isn't necessarily the latest version of a template." + "Version": "The unique identifier for the version of the message template to use for the message. If specified, this value must match the identifier for an existing template version. To retrieve a list of versions and version identifiers for a template, use the [Template Versions](https://docs.aws.amazon.com/pinpoint/latest/apireference/templates-template-name-template-type-versions.html) resource.\n\nIf you don't specify a value for this property, Amazon Pinpoint uses the *active version* of the template. The *active version* is typically the version of a template that's been most recently reviewed and approved for use, depending on your workflow. It isn't necessarily the latest version of a template." } }, "AWS::Pinpoint::Campaign.TemplateConfiguration": { @@ -39763,7 +39795,7 @@ "attributes": {}, "description": "The configuration settings of the Amazon Kinesis Data Streams destination for an Amazon QLDB journal stream.", "properties": { - "AggregationEnabled": "Enables QLDB to publish multiple data records in a single Kinesis Data Streams record, increasing the number of records sent per API call.\n\n*This option is enabled by default.* Record aggregation has important implications for processing records and requires de-aggregation in your stream consumer. To learn more, see [KPL Key Concepts](https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-concepts.html) and [Consumer De-aggregation](https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-consumer-deaggregation.html) in the *Amazon Kinesis Data Streams Developer Guide* .", + "AggregationEnabled": "Enables QLDB to publish multiple data records in a single Kinesis Data Streams record, increasing the number of records sent per API call.\n\nDefault: `True`\n\nRecord aggregation has important implications for processing records and requires de-aggregation in your stream consumer. To learn more, see [KPL Key Concepts](https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-concepts.html) and [Consumer De-aggregation](https://docs.aws.amazon.com/streams/latest/dev/kinesis-kpl-consumer-deaggregation.html) in the *Amazon Kinesis Data Streams Developer Guide* .", "StreamArn": "The Amazon Resource Name (ARN) of the Kinesis Data Streams resource." } }, @@ -40923,7 +40955,7 @@ "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`\n\nValid for: Aurora DB clusters and Multi-AZ DB clusters", "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* .\n\nValid for: Aurora DB clusters only", "EnableIAMDatabaseAuthentication": "A value that indicates whether to enable mapping of AWS Identity and Access Management (IAM) accounts to database accounts. By default, mapping is disabled.\n\nFor more information, see [IAM Database Authentication](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.html) in the *Amazon Aurora User Guide.*\n\nValid for: Aurora DB clusters only", - "Engine": "The name of the database engine to be used for this DB cluster.\n\nValid Values:\n\n- `aurora` (for MySQL 5.6-compatible Aurora)\n- `aurora-mysql` (for MySQL 5.7-compatible Aurora)\n- `aurora-postgresql`\n- `mysql`\n- `postgres`\n\nValid for: Aurora DB clusters and Multi-AZ DB clusters", + "Engine": "The name of the database engine to be used for this DB cluster.\n\nValid Values:\n\n- `aurora` (for MySQL 5.6-compatible Aurora)\n- `aurora-mysql` (for MySQL 5.7-compatible and MySQL 8.0-compatible Aurora)\n- `aurora-postgresql`\n- `mysql`\n- `postgres`\n\nValid for: Aurora DB clusters and Multi-AZ DB clusters", "EngineMode": "The DB engine mode of the DB cluster, either `provisioned` , `serverless` , `parallelquery` , `global` , or `multimaster` .\n\nThe `parallelquery` engine mode isn't required for Aurora MySQL version 1.23 and higher 1.x versions, and version 2.09 and higher 2.x versions.\n\nThe `global` engine mode isn't required for Aurora MySQL version 1.22 and higher 1.x versions, and `global` engine mode isn't required for any 2.x versions.\n\nThe `multimaster` engine mode only applies for DB clusters created with Aurora MySQL version 5.6.10a.\n\nFor Aurora PostgreSQL, the `global` engine mode isn't required, and both the `parallelquery` and the `multimaster` engine modes currently aren't supported.\n\nLimitations and requirements apply to some DB engine modes. For more information, see the following sections in the *Amazon Aurora User Guide* :\n\n- [Limitations of Aurora Serverless](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html#aurora-serverless.limitations)\n- [Limitations of Parallel Query](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-mysql-parallel-query.html#aurora-mysql-parallel-query-limitations)\n- [Limitations of Aurora Global Databases](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html#aurora-global-database.limitations)\n- [Limitations of Multi-Master Clusters](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-multi-master.html#aurora-multi-master-limitations)\n\nValid for: Aurora DB clusters only", "EngineVersion": "The version number of the database engine to use.\n\nTo list all of the available engine versions for `aurora` (for MySQL 5.6-compatible Aurora), use the following command:\n\n`aws rds describe-db-engine-versions --engine aurora --query \"DBEngineVersions[].EngineVersion\"`\n\nTo list all of the available engine versions for `aurora-mysql` (for MySQL 5.7-compatible Aurora), use the following command:\n\n`aws rds describe-db-engine-versions --engine aurora-mysql --query \"DBEngineVersions[].EngineVersion\"`\n\nTo list all of the available engine versions for `aurora-postgresql` , use the following command:\n\n`aws rds describe-db-engine-versions --engine aurora-postgresql --query \"DBEngineVersions[].EngineVersion\"`\n\nValid for: Aurora DB clusters and Multi-AZ DB clusters", "GlobalClusterIdentifier": "If you are configuring an Aurora global database cluster and want your Aurora DB cluster to be a secondary member in the global database cluster, specify the global cluster ID of the global database cluster. To define the primary database cluster of the global cluster, use the [AWS::RDS::GlobalCluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-globalcluster.html) resource.\n\nIf you aren't configuring a global database cluster, don't specify this property.\n\n> To remove the DB cluster from a global database cluster, specify an empty value for the `GlobalClusterIdentifier` property. \n\nFor information about Aurora global databases, see [Working with Amazon Aurora Global Databases](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html) in the *Amazon Aurora User Guide* .\n\nValid for: Aurora DB clusters only", @@ -41014,7 +41046,7 @@ }, "description": "The `AWS::RDS::DBClusterParameterGroup` resource creates a new Amazon RDS DB cluster parameter group.\n\nFor information about configuring parameters for Amazon Aurora DB clusters, see [Working with parameter groups](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithParamGroups.html) in the *Amazon Aurora User Guide* .\n\n> If you apply a parameter group to a 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.", "properties": { - "DBClusterParameterGroupName": "The name of the DB cluster parameter group.\n\nConstraints:\n\n- Must not match the name of an existing DB cluster parameter group.\n\nIf you don't specify a value for `DBClusterParameterGroupName` property, a name is automatically created for the DB cluster paramter group.\n\n> This value is stored as a lowercase string.", + "DBClusterParameterGroupName": "The name of the DB cluster parameter group.\n\nConstraints:\n\n- Must not match the name of an existing DB cluster parameter group.\n\nIf you don't specify a value for `DBClusterParameterGroupName` property, a name is automatically created for the DB cluster parameter group.\n\n> This value is stored as a lowercase string.", "Description": "A friendly description for this DB cluster parameter group.", "Family": "The DB cluster parameter group family name. A DB cluster parameter group can be associated with one and only one DB cluster parameter group family, and can be applied only to a DB cluster running a DB engine and engine version compatible with that DB cluster parameter group family.\n\n> The DB cluster parameter group family can't be changed when updating a DB cluster parameter group. \n\nTo list all of the available parameter group families, use the following command:\n\n`aws rds describe-db-engine-versions --query \"DBEngineVersions[].DBParameterGroupFamily\"`\n\nThe output contains duplicates.\n\nFor more information, see `[CreateDBClusterParameterGroup](https://docs.aws.amazon.com//AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html)` .", "Parameters": "Provides a list of parameters for the DB cluster parameter group.", @@ -41023,8 +41055,8 @@ }, "AWS::RDS::DBInstance": { "attributes": { - "CertificateDetails.CAIdentifier": "", - "CertificateDetails.ValidTill": "", + "CertificateDetails.CAIdentifier": "The CA identifier of the CA certificate used for the DB instance's server certificate.", + "CertificateDetails.ValidTill": "The expiration date of the DB instance\u2019s server certificate.", "DBInstanceArn": "The Amazon Resource Name (ARN) for the DB instance.", "DBSystemId": "The Oracle system ID (Oracle SID) for a container database (CDB). The Oracle SID is also the name of the CDB.\n\nThis setting is valid for RDS Custom only.", "DbiResourceId": "The AWS Region-unique, immutable identifier for the DB instance. This identifier is found in AWS CloudTrail log entries whenever the AWS KMS key for the DB instance is accessed.", @@ -41068,7 +41100,7 @@ "Engine": "The name of the database engine that you want to use for this DB instance.\n\n> When you are creating a DB instance, the `Engine` property is required. \n\nValid Values:\n\n- `aurora` (for MySQL 5.6-compatible Aurora)\n- `aurora-mysql` (for MySQL 5.7-compatible Aurora)\n- `aurora-postgresql`\n- `custom-oracle-ee`\n- `custom-oracle-ee-cdb`\n- `custom-sqlserver-ee`\n- `custom-sqlserver-se`\n- `custom-sqlserver-web`\n- `mariadb`\n- `mysql`\n- `oracle-ee`\n- `oracle-ee-cdb`\n- `oracle-se2`\n- `oracle-se2-cdb`\n- `postgres`\n- `sqlserver-ee`\n- `sqlserver-se`\n- `sqlserver-ex`\n- `sqlserver-web`", "EngineVersion": "The version number of the database engine to use.\n\nFor a list of valid engine versions, use the `DescribeDBEngineVersions` action.\n\nThe following are the database engines and links to information about the major and minor versions that are available with Amazon RDS. Not every database engine is available for every AWS Region.\n\n*Amazon Aurora*\n\nNot applicable. The version number of the database engine to be used by the DB instance is managed by the DB cluster.\n\n*MariaDB*\n\nSee [MariaDB on Amazon RDS Versions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MariaDB.html#MariaDB.Concepts.VersionMgmt) in the *Amazon RDS User Guide.*\n\n*Microsoft SQL Server*\n\nSee [Microsoft SQL Server Versions on Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_SQLServer.html#SQLServer.Concepts.General.VersionSupport) in the *Amazon RDS User Guide.*\n\n*MySQL*\n\nSee [MySQL on Amazon RDS Versions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt) in the *Amazon RDS User Guide.*\n\n*Oracle*\n\nSee [Oracle Database Engine Release Notes](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.PatchComposition.html) in the *Amazon RDS User Guide.*\n\n*PostgreSQL*\n\nSee [Supported PostgreSQL Database Versions](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.DBVersions) in the *Amazon RDS User Guide.*", "Iops": "The number of I/O operations per second (IOPS) that the database provisions. The value must be equal to or greater than 1000.\n\nIf you specify this property, you must follow the range of allowed ratios of your requested IOPS rate to the amount of storage that you allocate (IOPS to allocated storage). For example, you can provision an Oracle database instance with 1000 IOPS and 200 GiB of storage (a ratio of 5:1), or specify 2000 IOPS with 200 GiB of storage (a ratio of 10:1). For more information, see [Amazon RDS Provisioned IOPS Storage to Improve Performance](https://docs.aws.amazon.com/AmazonRDS/latest/DeveloperGuide/CHAP_Storage.html#USER_PIOPS) in the *Amazon RDS User Guide* .\n\n> If you specify `io1` for the `StorageType` property, then you must also specify the `Iops` property.", - "KmsKeyId": "The ARN of the AWS KMS key that's used to encrypt the DB instance, such as `arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef` . If you enable the StorageEncrypted property but don't specify this property, AWS CloudFormation uses the default KMS key. If you specify this property, you must set the StorageEncrypted property to true.\n\nIf you specify the `SourceDBInstanceIdentifier` property, the value is inherited from the source DB instance if the read replica is created in the same region.\n\nIf you create an encrypted read replica in a different AWS Region, then you must specify a KMS key for the destination AWS Region. KMS encryption keys are specific to the region that they're created in, and you can't use encryption keys from one region in another region.\n\nIf you specify the `SnapshotIdentifier` property, the `StorageEncrypted` property value is inherited from the snapshot, and if the DB instance is encrypted, the specified `KmsKeyId` property is used.\n\nIf you specify `DBSecurityGroups` , AWS CloudFormation ignores this property. To specify both 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/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html) in the *Amazon RDS User Guide* .\n\n*Amazon Aurora*\n\nNot applicable. The KMS key identifier is managed by the DB cluster.", + "KmsKeyId": "The ARN of the AWS KMS key that's used to encrypt the DB instance, such as `arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef` . If you enable the StorageEncrypted property but don't specify this property, AWS CloudFormation uses the default KMS key. If you specify this property, you must set the StorageEncrypted property to true.\n\nIf you specify the `SourceDBInstanceIdentifier` property, the value is inherited from the source DB instance if the read replica is created in the same region.\n\nIf you create an encrypted read replica in a different AWS Region, then you must specify a KMS key for the destination AWS Region. KMS encryption keys are specific to the region that they're created in, and you can't use encryption keys from one region in another region.\n\nIf you specify the `SnapshotIdentifier` property, the `StorageEncrypted` property value is inherited from the snapshot, and if the DB instance is encrypted, the specified `KmsKeyId` property is used.\n\nIf you specify `DBSecurityGroups` , AWS CloudFormation ignores this property. To specify both 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* .\n\n*Amazon Aurora*\n\nNot applicable. The KMS key identifier is managed by the DB cluster.", "LicenseModel": "License model information for this DB instance.\n\nValid values:\n\n- Aurora MySQL - `general-public-license`\n- Aurora PostgreSQL - `postgresql-license`\n- MariaDB - `general-public-license`\n- Microsoft SQL Server - `license-included`\n- MySQL - `general-public-license`\n- Oracle - `bring-your-own-license` or `license-included`\n- PostgreSQL - `postgresql-license`\n\n> If you've specified `DBSecurityGroups` and then you update the license model, AWS CloudFormation replaces the underlying DB instance. This will incur some interruptions to database availability.", "ManageMasterUserPassword": "A value that indicates whether to manage the master user password with AWS Secrets Manager.\n\nFor more information, see [Password management with AWS Secrets Manager](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-secrets-manager.html) in the *Amazon RDS User Guide.*\n\nConstraints:\n\n- Can't manage the master user password with AWS Secrets Manager if `MasterUserPassword` is specified.", "MasterUserPassword": "The password for the master user. The password can include any printable ASCII character except \"/\", \"\"\", or \"@\".\n\n*Amazon Aurora*\n\nNot applicable. The password for the master user is managed by the DB cluster.\n\n*MariaDB*\n\nConstraints: Must contain from 8 to 41 characters.\n\n*Microsoft SQL Server*\n\nConstraints: Must contain from 8 to 128 characters.\n\n*MySQL*\n\nConstraints: Must contain from 8 to 41 characters.\n\n*Oracle*\n\nConstraints: Must contain from 8 to 30 characters.\n\n*PostgreSQL*\n\nConstraints: Must contain from 8 to 128 characters.", @@ -41082,7 +41114,7 @@ "NetworkType": "The network type of the DB instance.\n\nValid values:\n\n- `IPV4`\n- `DUAL`\n\nThe network type is determined by the `DBSubnetGroup` specified for the DB instance. A `DBSubnetGroup` can support only the IPv4 protocol or the IPv4 and IPv6 protocols ( `DUAL` ).\n\nFor more information, see [Working with a DB instance in a VPC](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html) in the *Amazon RDS User Guide.*", "OptionGroupName": "Indicates that the DB instance should be associated with the specified option group.\n\nPermanent options, such as the TDE option for Oracle Advanced Security TDE, can't be removed from an option group. Also, that option group can't be removed from a DB instance once it is associated with a DB instance.", "PerformanceInsightsKMSKeyId": "The AWS KMS key identifier for encryption of Performance Insights data.\n\nThe KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key.\n\nIf you do not specify a value for `PerformanceInsightsKMSKeyId` , then Amazon RDS uses your default KMS key. There is a default KMS key for your AWS account. Your AWS account has a different default KMS key for each AWS Region.\n\nFor information about enabling Performance Insights, see [EnablePerformanceInsights](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-enableperformanceinsights) .", - "PerformanceInsightsRetentionPeriod": "The amount of time, in days, to retain Performance Insights data. Valid values are 7 or 731 (2 years).\n\nFor information about enabling Performance Insights, see [EnablePerformanceInsights](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-enableperformanceinsights) .", + "PerformanceInsightsRetentionPeriod": "The number of days to retain Performance Insights data. The default is 7 days. The following values are valid:\n\n- 7\n- *month* * 31, where *month* is a number of months from 1-23\n- 731\n\nFor example, the following values are valid:\n\n- 93 (3 months * 31)\n- 341 (11 months * 31)\n- 589 (19 months * 31)\n- 731\n\nIf you specify a retention period such as 94, which isn't a valid value, RDS issues an error.\n\nThis setting doesn't apply to RDS Custom.", "Port": "The port number on which the database accepts connections.\n\n*Amazon Aurora*\n\nNot applicable. The port number is managed by the DB cluster.", "PreferredBackupWindow": "The daily time range during which automated backups are created if automated backups are enabled, using the `BackupRetentionPeriod` parameter. For more information, see [Backup Window](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithAutomatedBackups.html#USER_WorkingWithAutomatedBackups.BackupWindow) in the *Amazon RDS User Guide.*\n\nConstraints:\n\n- Must be in the format `hh24:mi-hh24:mi` .\n- Must be in Universal Coordinated Time (UTC).\n- Must not conflict with the preferred maintenance window.\n- Must be at least 30 minutes.\n\n*Amazon Aurora*\n\nNot applicable. The daily time range for creating automated backups is managed by the DB cluster.", "PreferredMaintenanceWindow": "The weekly time range during which system maintenance can occur, in Universal Coordinated Time (UTC).\n\nFormat: `ddd:hh24:mi-ddd:hh24:mi`\n\nThe default is a 30-minute window selected at random from an 8-hour block of time for each AWS Region, occurring on a random day of the week. To see the time blocks available, see [Adjusting the Preferred DB Instance Maintenance Window](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Maintenance.html#AdjustingTheMaintenanceWindow) in the *Amazon RDS User Guide.*\n\n> This property applies when AWS CloudFormation initially creates the DB instance. If you use AWS CloudFormation to update the DB instance, those updates are applied immediately. \n\nConstraints: Minimum 30-minute window.", @@ -41186,7 +41218,7 @@ "description": "Specifies the details of authentication used by a proxy to log in as a specific database user.", "properties": { "AuthScheme": "The type of authentication that the proxy uses for connections from the proxy to the underlying database.\n\nValid Values: `SECRETS`", - "ClientPasswordAuthType": "", + "ClientPasswordAuthType": "Specifies the details of authentication used by a proxy to log in as a specific database user.", "Description": "A user-specified description about the authentication used by a proxy to log in as a specific database user.", "IAMAuth": "Whether to require or disallow AWS Identity and Access Management (IAM) authentication for connections to the proxy. The `ENABLED` value is valid only for proxies with RDS for Microsoft SQL Server.\n\nValid Values: `ENABLED | DISABLED | REQUIRED`", "SecretArn": "The Amazon Resource Name (ARN) representing the secret that the proxy uses to authenticate to the RDS DB instance or Aurora DB cluster. These secrets are stored within Amazon Secrets Manager." @@ -41206,7 +41238,7 @@ "Endpoint": "The custom endpoint for the RDS DB instance or Aurora DB cluster.", "IsDefault": "A value that indicates whether this endpoint is the default endpoint for the associated DB proxy. Default DB proxy endpoints always have read/write capability. Other endpoints that you associate with the DB proxy can be either read/write or read-only.", "Ref": "`Ref` returns the name of the DB proxy endpoint.", - "TargetRole": "", + "TargetRole": "A value that indicates whether the DB proxy endpoint can be used for read/write or read-only operations.", "VpcId": "The VPC ID of the DB proxy endpoint." }, "description": "The `AWS::RDS::DBProxyEndpoint` resource creates or updates a DB proxy endpoint. You can use custom proxy endpoints to access a proxy through a different VPC than the proxy's default VPC.\n\nFor more information about RDS Proxy, see [AWS::RDS::DBProxy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxy.html) .", @@ -41459,8 +41491,8 @@ "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-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 or hyphens. The user name can't be `PUBLIC` .\n- Must contain only lowercase letters, numbers, underscore, plus sign, period (dot), at symbol (@), or hyphen.\n- The first character must be a letter.\n- Must not contain a colon (:) or a slash (/).\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.", + "MasterUserPassword": "The password associated with the admin user 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 for the cluster that is being created.\n\nConstraints:\n\n- Must be 1 - 128 alphanumeric characters or hyphens. The user name can't be `PUBLIC` .\n- Must contain only lowercase letters, numbers, underscore, plus sign, period (dot), at symbol (@), or hyphen.\n- The first character must be a letter.\n- Must not contain a colon (:) or a slash (/).\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.", "OwnerAccount": "The AWS account used to create or copy the snapshot. Required if you are restoring a snapshot you do not own, optional if you own the snapshot.", @@ -41470,7 +41502,7 @@ "ResourceAction": "", "RevisionTarget": "", "RotateEncryptionKey": "", - "SnapshotClusterIdentifier": "The name of the cluster the source snapshot was created from. This parameter is required if your IAM user has a policy containing a snapshot resource element that specifies anything other than * for the cluster name.", + "SnapshotClusterIdentifier": "The name of the cluster the source snapshot was created from. This parameter is required if your IAM user or role has a policy containing a snapshot resource element that specifies anything other than * for the cluster name.", "SnapshotCopyGrantName": "The name of the snapshot copy grant.", "SnapshotCopyManual": "Indicates whether to apply the snapshot retention period to newly copied manual snapshots instead of automated snapshots.", "SnapshotCopyRetentionPeriod": "The number of days to retain automated snapshots in the destination AWS Region after they are copied from the source AWS Region .\n\nBy default, this only changes the retention period of copied automated snapshots.\n\nIf you decrease the retention period for automated snapshots that are copied to a destination AWS Region , Amazon Redshift deletes any existing automated snapshots that were copied to the destination AWS Region and that fall outside of the new retention period.\n\nConstraints: Must be at least 1 and no more than 35 for automated snapshots.\n\nIf you specify the `manual` option, only newly copied manual snapshots will have the new retention period.\n\nIf you specify the value of -1 newly copied manual snapshots are retained indefinitely.\n\nConstraints: The number of days must be either -1 or an integer between 1 and 3,653 for manual snapshots.", @@ -41497,13 +41529,13 @@ }, "AWS::Redshift::ClusterParameterGroup": { "attributes": { - "ParameterGroupName": "The name of the parameter group.", "Ref": "`Ref` returns the resource name. For example:\n\n`{ \"Ref\": \"myClusterParameterGroup\" }`\n\nFor the Amazon Redshift cluster parameter group `myClusterParameterGroup` , `Ref` returns the name of the cluster parameter group." }, "description": "Describes a parameter group.", "properties": { "Description": "The description of the parameter group.", "ParameterGroupFamily": "The name of the cluster parameter group family that this cluster parameter group is compatible with.", + "ParameterGroupName": "The name of the cluster parameter group.", "Parameters": "An array of parameters to be modified. A maximum of 20 parameters can be modified in a single request.\n\nFor each parameter to be modified, you must supply at least the parameter name and parameter value; other name-value pairs of the parameter are optional.\n\nFor the workload management (WLM) configuration, you must supply all the name-value pairs in the wlm_json_configuration parameter.", "Tags": "The list of tags for the cluster parameter group." } @@ -42053,10 +42085,10 @@ "AppArn": "The Amazon Resource Name (ARN) of the app.", "Ref": "The returned Amazon Resource Name (ARN) for the app." }, - "description": "Creates a Resilience Hub application. A Resilience Hub application is a collection of AWS resources structured to prevent and recover AWS application disruptions. To describe a Resilience Hub application, you provide an application name, resources from one or more\u2013up to five\u2013 AWS CloudFormation stacks, and an appropriate resiliency policy.\n\nAfter you create a Resilience Hub application, you publish it so that you can run a resiliency assessment on it. You can then use recommendations from the assessment to improve resiliency by running another assessment, comparing results, and then iterating the process until you achieve your goals for recovery time objective (RTO) and recovery point objective (RPO).", + "description": "Creates an AWS Resilience Hub application. An AWS Resilience Hub application is a collection of AWS resources structured to prevent and recover AWS application disruptions. To describe a AWS Resilience Hub application, you provide an application name, resources from one or more\u2013up to five\u2013 AWS CloudFormation stacks, and an appropriate resiliency policy.\n\nAfter you create an AWS Resilience Hub application, you publish it so that you can run a resiliency assessment on it. You can then use recommendations from the assessment to improve resiliency by running another assessment, comparing results, and then iterating the process until you achieve your goals for recovery time objective (RTO) and recovery point objective (RPO).", "properties": { "AppAssessmentSchedule": "Assessment execution schedule with 'Daily' or 'Disabled' values.", - "AppTemplateBody": "A string containing a full Resilience Hub app template body.", + "AppTemplateBody": "A string containing a full AWS Resilience Hub app template body.", "Description": "The optional description for an app.", "Name": "The name for the application.", "ResiliencyPolicyArn": "The Amazon Resource Name (ARN) of the resiliency policy.", @@ -42071,7 +42103,7 @@ "AwsAccountId": "The AWS account that owns the physical resource.", "AwsRegion": "The AWS Region that the physical resource is located in.", "Identifier": "The identifier of the physical resource.", - "Type": "Specifies the type of physical resource identifier.\n\n- **Arn** - The resource identifier is an Amazon Resource Name (ARN) .\n- **Native** - The resource identifier is a Resilience Hub-native identifier." + "Type": "Specifies the type of physical resource identifier.\n\n- **Arn** - The resource identifier is an Amazon Resource Name (ARN) .\n- **Native** - The resource identifier is an AWS Resilience Hub -native identifier." } }, "AWS::ResilienceHub::App.ResourceMapping": { @@ -42656,12 +42688,12 @@ "AWS::Route53RecoveryControl::Cluster": { "attributes": { "ClusterArn": "The Amazon Resource Name (ARN) of the cluster.", + "ClusterEndpoints": "Endpoints for the cluster.", "Ref": "`Ref` returns the `ClusterArn` object.", "Status": "Deployment status of a resource. Status can be one of the following: PENDING, DEPLOYED, PENDING_DELETION." }, "description": "Returns an array of all the clusters in an account.", "properties": { - "ClusterEndpoints": "", "Name": "Name of the cluster. You can use any non-white space character in the name.", "Tags": "The value for a tag." } @@ -47767,12 +47799,13 @@ "properties": { "ExcludeCharacters": "A string of the characters that you don't want in the password.", "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. 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) .\n\nYou can specify `MasterSecretArn` or `SuperuserSecretArn` but not both. They represent the same superuser secret.", - "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.\n\nYou can specify `MasterSecretKmsKeyArn` or `SuperuserSecretKmsKeyArn` but not both. They represent the same superuser secret KMS key .", + "MasterSecretArn": "The ARN of the secret that contains superuser credentials, if you use the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . CloudFormation grants the execution role for the Lambda rotation function `GetSecretValue` permission to the secret in this property. For more information, see [Lambda rotation function execution role permissions for Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions-function.html) .\n\nYou must create the superuser secret before you can set this property.\n\nYou must also include the superuser secret ARN as a key in the JSON of the rotating secret so that the Lambda rotation function can find it. CloudFormation does not hardcode secret ARNs in the Lambda rotation function, so you can use the function to rotate multiple secrets. For more information, see [JSON structure of Secrets Manager secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_secret_json_structure.html) .\n\nYou can specify `MasterSecretArn` or `SuperuserSecretArn` but not both. They represent the same superuser secret.", + "MasterSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager used to encrypt the superuser secret, if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) and the superuser secret is encrypted with a customer managed key. You don't need to specify this property if the superuser secret is encrypted using the key `aws/secretsmanager` . CloudFormation grants the execution role for the Lambda rotation function `Decrypt` , `DescribeKey` , and `GenerateDataKey` permission to the key in this property. For more information, see [Lambda rotation function execution role permissions for Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions-function.html) .\n\nYou can specify `MasterSecretKmsKeyArn` or `SuperuserSecretKmsKeyArn` but not both. They represent the same superuser secret KMS key .", "RotationLambdaName": "The name of the Lambda rotation function.", "RotationType": "The rotation template to base the rotation function on, one of the following:\n\n- `MySQLSingleUser` to use the template [SecretsManagerRDSMySQLRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mysql-singleuser) .\n- `MySQLMultiUser` to use the template [SecretsManagerRDSMySQLRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mysql-multiuser) .\n- `PostgreSQLSingleUser` to use the template [SecretsManagerRDSPostgreSQLRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-postgre-singleuser)\n- `PostgreSQLMultiUser` to use the template [SecretsManagerRDSPostgreSQLRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-postgre-multiuser) .\n- `OracleSingleUser` to use the template [SecretsManagerRDSOracleRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-oracle-singleuser) .\n- `OracleMultiUser` to use the template [SecretsManagerRDSOracleRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-oracle-multiuser) .\n- `MariaDBSingleUser` to use the template [SecretsManagerRDSMariaDBRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mariadb-singleuser) .\n- `MariaDBMultiUser` to use the template [SecretsManagerRDSMariaDBRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mariadb-multiuser) .\n- `SQLServerSingleUser` to use the template [SecretsManagerRDSSQLServerRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-sqlserver-singleuser) .\n- `SQLServerMultiUser` to use the template [SecretsManagerRDSSQLServerRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-sqlserver-multiuser) .\n- `RedshiftSingleUser` to use the template [SecretsManagerRedshiftRotationSingleUsr](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-redshift-singleuser) .\n- `RedshiftMultiUser` to use the template [SecretsManagerRedshiftRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-redshift-multiuser) .\n- `MongoDBSingleUser` to use the template [SecretsManagerMongoDBRotationSingleUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mongodb-singleuser) .\n- `MongoDBMultiUser` to use the template [SecretsManagerMongoDBRotationMultiUser](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_available-rotation-templates.html#sar-template-mongodb-multiuser) .", - "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) .\n\nYou can specify `MasterSecretArn` or `SuperuserSecretArn` but not both. They represent the same superuser secret.", - "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.\n\nYou can specify `MasterSecretKmsKeyArn` or `SuperuserSecretKmsKeyArn` but not both. They represent the same superuser secret KMS key .", + "Runtime": "The Python runtime version associated with the Lambda function.", + "SuperuserSecretArn": "The ARN of the secret that contains superuser credentials, if you use the [Alternating users rotation strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) . CloudFormation grants the execution role for the Lambda rotation function `GetSecretValue` permission to the secret in this property. For more information, see [Lambda rotation function execution role permissions for Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions-function.html) .\n\nYou must create the superuser secret before you can set this property.\n\nYou must also include the superuser secret ARN as a key in the JSON of the rotating secret so that the Lambda rotation function can find it. CloudFormation does not hardcode secret ARNs in the Lambda rotation function, so you can use the function to rotate multiple secrets. For more information, see [JSON structure of Secrets Manager secrets](https://docs.aws.amazon.com/secretsmanager/latest/userguide/reference_secret_json_structure.html) .\n\nYou can specify `MasterSecretArn` or `SuperuserSecretArn` but not both. They represent the same superuser secret.", + "SuperuserSecretKmsKeyArn": "The ARN of the KMS key that Secrets Manager used to encrypt the superuser secret, if you use the [alternating users strategy](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets_strategies.html#rotating-secrets-two-users) and the superuser secret is encrypted with a customer managed key. You don't need to specify this property if the superuser secret is encrypted using the key `aws/secretsmanager` . CloudFormation grants the execution role for the Lambda rotation function `Decrypt` , `DescribeKey` , and `GenerateDataKey` permission to the key in this property. For more information, see [Lambda rotation function execution role permissions for Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/rotating-secrets-required-permissions-function.html) .\n\nYou can specify `MasterSecretKmsKeyArn` or `SuperuserSecretKmsKeyArn` but not both. They represent the same superuser secret KMS key .", "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." } @@ -49536,7 +49569,7 @@ "properties": { "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 logs 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 `REDACTED` .\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` ." } }, @@ -50517,7 +50550,7 @@ }, "description": "> This is the latest version of *AWS WAF* , named AWS WAF V2, released in November, 2019. For information, including how to migrate your AWS WAF resources from the prior release, see the [AWS WAF Developer Guide](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) . \n\nUse a web ACL association to define an association between a web ACL and a regional application resource, to protect the resource. A regional application can be an Application Load Balancer (ALB), an Amazon API Gateway REST API, an AWS AppSync GraphQL API, or an Amazon Cognito user pool.\n\nFor Amazon CloudFront , don't use this resource. Instead, use your CloudFront distribution configuration. To associate a web ACL with a distribution, provide the Amazon Resource Name (ARN) of the `WebACL` to your CloudFront distribution configuration. To disassociate a web ACL, provide an empty ARN. For information, see [AWS::CloudFront::Distribution](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-distribution.html) .\n\nWhen you create a web ACL or make changes to a web ACL or web ACL components, like rules and rule groups, AWS WAF propagates the changes everywhere that the web ACL and its components are stored and used. Your changes are applied within seconds, but there might be a brief period of inconsistency when the changes have arrived in some places and not in others. So, for example, if you change a rule action setting, the action might be the old action in one area and the new action in another area. Or if you add an IP address to an IP set used in a blocking rule, the new address might briefly be blocked in one area while still allowed in another. This temporary inconsistency can occur when you first associate a web ACL with an AWS resource and when you change a web ACL that is already associated with a resource. Generally, any inconsistencies of this type last only a few seconds.", "properties": { - "ResourceArn": "The Amazon Resource Name (ARN) of the resource to associate with the web ACL.\n\nThe ARN must be in one of the following formats:\n\n- For an Application Load Balancer: `arn:aws:elasticloadbalancing: *region* : *account-id* :loadbalancer/app/ *load-balancer-name* / *load-balancer-id*`\n- For an Amazon API Gateway REST API: `arn:aws:apigateway: *region* ::/restapis/ *api-id* /stages/ *stage-name*`\n- For an AWS AppSync GraphQL API: `arn:aws:appsync: *region* : *account-id* :apis/ *GraphQLApiId*`\n- For an Amazon Cognito user pool: `arn:aws:cognito-idp: *region* : *account-id* :userpool/ *user-pool-id*`", + "ResourceArn": "The Amazon Resource Name (ARN) of the resource to associate with the web ACL.\n\nThe ARN must be in one of the following formats:\n\n- For an Application Load Balancer: `arn:aws:elasticloadbalancing: *region* : *account-id* :loadbalancer/app/ *load-balancer-name* / *load-balancer-id*`\n- For an Amazon API Gateway REST API: `arn:aws:apigateway: *region* ::/restapis/ *api-id* /stages/ *stage-name*`\n- For an AWS AppSync GraphQL API: `arn:aws:appsync: *region* : *account-id* :apis/ *GraphQLApiId*`\n- For an Amazon Cognito user pool: `arn:aws:cognito-idp: *region* : *account-id* :userpool/ *user-pool-id*`\n- For an AWS App Runner service: `arn:aws:apprunner: *region* : *account-id* :service/ *apprunner-service-name* / *apprunner-service-id*`", "WebACLArn": "The Amazon Resource Name (ARN) of the web ACL that you want to associate with the resource." } }, diff --git a/packages/@aws-cdk/core/package.json b/packages/@aws-cdk/core/package.json index 0c2dcf5bfe6a4..5a63f16d1761d 100644 --- a/packages/@aws-cdk/core/package.json +++ b/packages/@aws-cdk/core/package.json @@ -186,12 +186,12 @@ "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/fs-extra": "^9.0.13", "@types/jest": "^27.5.2", "@types/lodash": "^4.14.191", "@types/minimatch": "^3.0.5", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "@types/sinon": "^9.0.11", "fast-check": "^2.25.0", "jest": "^27.5.1", diff --git a/packages/@aws-cdk/core/test/private/asset-staging.test.ts b/packages/@aws-cdk/core/test/private/asset-staging.test.ts index 31d316eed30af..adcbf71ffe5d9 100644 --- a/packages/@aws-cdk/core/test/private/asset-staging.test.ts +++ b/packages/@aws-cdk/core/test/private/asset-staging.test.ts @@ -3,6 +3,8 @@ import * as sinon from 'sinon'; import { AssetStaging, DockerImage } from '../../lib'; import { AssetBundlingBindMount, AssetBundlingVolumeCopy } from '../../lib/private/asset-staging'; +const DOCKER_CMD = process.env.CDK_DOCKER ?? 'docker'; + describe('bundling', () => { afterEach(() => { sinon.restore(); @@ -29,25 +31,25 @@ describe('bundling', () => { helper.run(); // volume Creation - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'volume', 'create', sinon.match(/assetInput.*/g), ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'volume', 'create', sinon.match(/assetOutput.*/g), ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // volume removal - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'volume', 'rm', sinon.match(/assetInput.*/g), ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'volume', 'rm', sinon.match(/assetOutput.*/g), ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // prepare copy container - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'run', '--name', sinon.match(/copyContainer.*/g), '-v', sinon.match(/assetInput.*/g), @@ -59,22 +61,22 @@ describe('bundling', () => { ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // delete copy container - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'rm', sinon.match(/copyContainer.*/g), ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // copy files to copy container - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'cp', `${options.sourcePath}/.`, `${helper.copyContainerName}:${AssetStaging.BUNDLING_INPUT_DIR}`, ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // copy files from copy container to host - expect(spawnSyncStub.calledWith('docker', sinon.match([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match([ 'cp', `${helper.copyContainerName}:${AssetStaging.BUNDLING_OUTPUT_DIR}/.`, options.bundleDir, ]), { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); // actual docker run - expect(spawnSyncStub.calledWith('docker', sinon.match.array.contains([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match.array.contains([ 'run', '--rm', '--volumes-from', helper.copyContainerName, 'alpine', @@ -103,7 +105,7 @@ describe('bundling', () => { helper.run(); // actual docker run with bind mount is called - expect(spawnSyncStub.calledWith('docker', sinon.match.array.contains([ + expect(spawnSyncStub.calledWith(DOCKER_CMD, sinon.match.array.contains([ 'run', '--rm', '-v', 'alpine', diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 1dfc4ac772b77..43d88f5e7a823 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -89,11 +89,11 @@ "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", - "@types/aws-lambda": "^8.10.110", + "@types/aws-lambda": "^8.10.111", "@types/fs-extra": "^9.0.13", "@types/jest": "^27.5.2", "@types/sinon": "^9.0.11", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "fs-extra": "^9.1.0", "nock": "^13.3.0", diff --git a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md index b9f524ecb972a..b1ef62b576767 100644 --- a/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md +++ b/packages/@aws-cdk/cx-api/FEATURE_FLAGS.md @@ -46,6 +46,8 @@ Flags come in three types: | [@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup](#aws-cdkaws-codedeployremovealarmsfromdeploymentgroup) | Remove CloudWatch alarms from deployment group | 2.65.0 | (fix) | | [@aws-cdk/aws-rds:databaseProxyUniqueResourceName](#aws-cdkaws-rdsdatabaseproxyuniqueresourcename) | Use unique resource name for Database Proxy | 2.65.0 | (fix) | | [@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId](#aws-cdkaws-apigatewayauthorizerchangedeploymentlogicalid) | Include authorizer configuration in the calculation of the API deployment logical ID. | 2.66.0 | (fix) | +| [@aws-cdk/aws-ec2:launchTemplateDefaultUserData](#aws-cdkaws-ec2launchtemplatedefaultuserdata) | Define user data for a launch template by default when a machine image is provided. | V2NEXT | (fix) | +| [@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments](#aws-cdkaws-secretsmanageruseattachedsecretresourcepolicyforsecrettargetattachments) | SecretTargetAttachments uses the ResourcePolicy of the attached Secret. | V2NEXT | (fix) | @@ -82,7 +84,9 @@ The following json shows the current recommended set of flags, as `cdk init` wou "@aws-cdk/customresources:installLatestAwsSdkDefault": false, "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, - "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true } } ``` @@ -834,4 +838,41 @@ calculation, so any changes made to an authorizer will create a new deployment. | 2.66.0 | `false` | `true` | +### @aws-cdk/aws-ec2:launchTemplateDefaultUserData + +*Define user data for a launch template by default when a machine image is provided.* (fix) + +The ec2.LaunchTemplate construct did not define user data when a machine image is +provided despite the document. If this is set, a user data is automatically defined +according to the OS of the machine image. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| V2NEXT | `false` | `true` | + + +### @aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments + +*SecretTargetAttachments uses the ResourcePolicy of the attached Secret.* (fix) + +Enable this feature flag to make SecretTargetAttachments use the ResourcePolicy of the attached Secret. +SecretTargetAttachments are created to connect a Secret to a target resource. +In CDK code, they behave like regular Secret and can be used as a stand-in in most situations. +Previously, adding to the ResourcePolicy of a SecretTargetAttachment did attempt to create a separate ResourcePolicy for the same Secret. +However Secrets can only have a single ResourcePolicy, causing the CloudFormation deployment to fail. + +When enabling this feature flag for an existing Stack, ResourcePolicies created via a SecretTargetAttachment will need replacement. +This won't be possible without intervention due to limitation outlined above. +First remove all permissions granted to the Secret and deploy without the ResourcePolicies. +Then you can re-add the permissions and deploy again. + + +| Since | Default | Recommended | +| ----- | ----- | ----- | +| (not in v1) | | | +| V2NEXT | `false` | `true` | + + diff --git a/packages/@aws-cdk/cx-api/lib/features.ts b/packages/@aws-cdk/cx-api/lib/features.ts index 8850205a5eec2..1ae7e4dd6f2fc 100644 --- a/packages/@aws-cdk/cx-api/lib/features.ts +++ b/packages/@aws-cdk/cx-api/lib/features.ts @@ -81,6 +81,8 @@ export const AWS_CUSTOM_RESOURCE_LATEST_SDK_DEFAULT = '@aws-cdk/customresources: export const DATABASE_PROXY_UNIQUE_RESOURCE_NAME = '@aws-cdk/aws-rds:databaseProxyUniqueResourceName'; export const CODEDEPLOY_REMOVE_ALARMS_FROM_DEPLOYMENT_GROUP = '@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup'; export const APIGATEWAY_AUTHORIZER_CHANGE_DEPLOYMENT_LOGICAL_ID = '@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId'; +export const EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA = '@aws-cdk/aws-ec2:launchTemplateDefaultUserData'; +export const SECRETS_MANAGER_TARGET_ATTACHMENT_RESOURCE_POLICY = '@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments'; export const FLAGS: Record = { ////////////////////////////////////////////////////////////////////// @@ -661,6 +663,7 @@ export const FLAGS: Record = { recommendedValue: true, }, + ////////////////////////////////////////////////////////////////////// [APIGATEWAY_AUTHORIZER_CHANGE_DEPLOYMENT_LOGICAL_ID]: { type: FlagType.BugFix, summary: 'Include authorizer configuration in the calculation of the API deployment logical ID.', @@ -673,6 +676,39 @@ export const FLAGS: Record = { introducedIn: { v2: '2.66.0' }, recommendedValue: true, }, + + ////////////////////////////////////////////////////////////////////// + [EC2_LAUNCH_TEMPLATE_DEFAULT_USER_DATA]: { + type: FlagType.BugFix, + summary: 'Define user data for a launch template by default when a machine image is provided.', + detailsMd: ` + The ec2.LaunchTemplate construct did not define user data when a machine image is + provided despite the document. If this is set, a user data is automatically defined + according to the OS of the machine image. + `, + recommendedValue: true, + introducedIn: { v2: 'V2NEXT' }, + }, + + ////////////////////////////////////////////////////////////////////// + [SECRETS_MANAGER_TARGET_ATTACHMENT_RESOURCE_POLICY]: { + type: FlagType.BugFix, + summary: 'SecretTargetAttachments uses the ResourcePolicy of the attached Secret.', + detailsMd: ` + Enable this feature flag to make SecretTargetAttachments use the ResourcePolicy of the attached Secret. + SecretTargetAttachments are created to connect a Secret to a target resource. + In CDK code, they behave like regular Secret and can be used as a stand-in in most situations. + Previously, adding to the ResourcePolicy of a SecretTargetAttachment did attempt to create a separate ResourcePolicy for the same Secret. + However Secrets can only have a single ResourcePolicy, causing the CloudFormation deployment to fail. + + When enabling this feature flag for an existing Stack, ResourcePolicies created via a SecretTargetAttachment will need replacement. + This won't be possible without intervention due to limitation outlined above. + First remove all permissions granted to the Secret and deploy without the ResourcePolicies. + Then you can re-add the permissions and deploy again. + `, + recommendedValue: true, + introducedIn: { v2: 'V2NEXT' }, + }, }; const CURRENT_MV = 'v2'; diff --git a/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES b/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES index 25381811df08b..2df6fb89cca98 100644 --- a/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES +++ b/packages/@aws-cdk/integ-runner/THIRD_PARTY_LICENSES @@ -156,7 +156,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE ---------------- -** aws-sdk@2.1317.0 - https://www.npmjs.com/package/aws-sdk/v/2.1317.0 | Apache-2.0 +** aws-sdk@2.1325.0 - https://www.npmjs.com/package/aws-sdk/v/2.1325.0 | Apache-2.0 AWS SDK for JavaScript Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -1534,7 +1534,7 @@ THE SOFTWARE. ---------------- -** readable-stream@2.3.7 - https://www.npmjs.com/package/readable-stream/v/2.3.7 | MIT +** readable-stream@2.3.8 - https://www.npmjs.com/package/readable-stream/v/2.3.8 | MIT Node.js is licensed for use as follows: """ @@ -1586,7 +1586,7 @@ IN THE SOFTWARE. ---------------- -** readable-stream@3.6.0 - https://www.npmjs.com/package/readable-stream/v/3.6.0 | MIT +** readable-stream@3.6.1 - https://www.npmjs.com/package/readable-stream/v/3.6.1 | MIT Node.js is licensed for use as follows: """ @@ -2263,7 +2263,7 @@ OTHER DEALINGS IN THE SOFTWARE. ---------------- -** workerpool@6.3.1 - https://www.npmjs.com/package/workerpool/v/6.3.1 | Apache-2.0 +** workerpool@6.4.0 - https://www.npmjs.com/package/workerpool/v/6.4.0 | Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -2452,7 +2452,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (C) 2014-2022 Jos de Jong wjosdejong@gmail.com + Copyright (C) 2014-2023 Jos de Jong wjosdejong@gmail.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/packages/@aws-cdk/integ-runner/package.json b/packages/@aws-cdk/integ-runner/package.json index 5aa94108aeb42..d51ee787172ce 100644 --- a/packages/@aws-cdk/integ-runner/package.json +++ b/packages/@aws-cdk/integ-runner/package.json @@ -75,7 +75,7 @@ "aws-cdk": "0.0.0", "chalk": "^4", "fs-extra": "^9.1.0", - "workerpool": "^6.3.1", + "workerpool": "^6.4.0", "yargs": "^16.2.0" }, "repository": { diff --git a/packages/@aws-cdk/integ-tests/package.json b/packages/@aws-cdk/integ-tests/package.json index 5ff680a5d142e..26955f48c4e18 100644 --- a/packages/@aws-cdk/integ-tests/package.json +++ b/packages/@aws-cdk/integ-tests/package.json @@ -67,7 +67,7 @@ "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^9.0.13", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "aws-sdk-mock": "5.6.0", "jest": "^27.5.1", "nock": "^13.3.0", diff --git a/packages/@aws-cdk/lambda-layer-awscli/package.json b/packages/@aws-cdk/lambda-layer-awscli/package.json index 70fbd525300cf..a9661d7872f3b 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/package.json +++ b/packages/@aws-cdk/lambda-layer-awscli/package.json @@ -84,7 +84,7 @@ "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/asset-awscli-v1": "^2.2.69", + "@aws-cdk/asset-awscli-v1": "^2.2.85", "constructs": "^10.0.0" }, "homepage": "https://github.com/aws/aws-cdk", 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 326a2d93e1673..33fc33d129d07 100644 --- a/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json +++ b/packages/@aws-cdk/lambda-layer-node-proxy-agent/package.json @@ -84,7 +84,7 @@ "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", "@aws-cdk/core": "0.0.0", - "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.58", + "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.71", "constructs": "^10.0.0" }, "homepage": "https://github.com/aws/aws-cdk", diff --git a/packages/@aws-cdk/pipelines/package.json b/packages/@aws-cdk/pipelines/package.json index 3c80bc8c72978..22003dab4cd5f 100644 --- a/packages/@aws-cdk/pipelines/package.json +++ b/packages/@aws-cdk/pipelines/package.json @@ -51,7 +51,7 @@ "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", - "aws-sdk": "^2.1317.0" + "aws-sdk": "^2.1325.0" }, "peerDependencies": { "@aws-cdk/aws-codebuild": "0.0.0", diff --git a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts index 580648a5fca08..be429408405bd 100644 --- a/packages/@aws-cdk/region-info/build-tools/fact-tables.ts +++ b/packages/@aws-cdk/region-info/build-tools/fact-tables.ts @@ -527,6 +527,44 @@ export const FIREHOSE_CIDR_BLOCKS: { [region: string]: string } = { }; const ADOT_LAMBDA_LAYER_JAVA_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.21.1': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-1:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-wrapper-arm64-ver-1-21-1:1', + }, + }, '1.21.0': { x86_64: { 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-wrapper-amd64-ver-1-21-0:1', @@ -608,6 +646,44 @@ const ADOT_LAMBDA_LAYER_JAVA_SDK_ARNS: { [version: string]: { [arch: string]: { const ADOT_LAMBDA_LAYER_JAVA_AUTO_INSTRUMENTATION_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } }; } = { + '1.21.1': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-1:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-java-agent-arm64-ver-1-21-1:1', + }, + }, '1.21.0': { x86_64: { 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-java-agent-amd64-ver-1-21-0:1', @@ -687,6 +763,44 @@ const ADOT_LAMBDA_LAYER_JAVA_AUTO_INSTRUMENTATION_ARNS: { }; const ADOT_LAMBDA_LAYER_JAVASCRIPT_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.9.1': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-nodejs-amd64-ver-1-9-1:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-nodejs-arm64-ver-1-9-1:1', + }, + }, '1.8.0': { x86_64: { 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-nodejs-amd64-ver-1-8-0:2', @@ -766,6 +880,44 @@ const ADOT_LAMBDA_LAYER_JAVASCRIPT_SDK_ARNS: { [version: string]: { [arch: strin }; const ADOT_LAMBDA_LAYER_PYTHON_SDK_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '1.16.0': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-python-amd64-ver-1-16-0:1', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-python-arm64-ver-1-16-0:1', + }, + }, '1.15.0': { x86_64: { 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-amd64-ver-1-15-0:2', @@ -845,6 +997,44 @@ const ADOT_LAMBDA_LAYER_PYTHON_SDK_ARNS: { [version: string]: { [arch: string]: }; const ADOT_LAMBDA_LAYER_GENERIC_ARNS: { [version: string]: { [arch: string]: { [region: string]: string } } } = { + '0.70.0': { + x86_64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-collector-amd64-ver-0-70-0:4', + }, + arm64: { + 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'ap-northeast-2': 'arn:aws:lambda:ap-northeast-2:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'ap-south-1': 'arn:aws:lambda:ap-south-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'ap-southeast-1': 'arn:aws:lambda:ap-southeast-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'ap-southeast-2': 'arn:aws:lambda:ap-southeast-2:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'ca-central-1': 'arn:aws:lambda:ca-central-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'eu-central-1': 'arn:aws:lambda:eu-central-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'eu-north-1': 'arn:aws:lambda:eu-north-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'eu-west-1': 'arn:aws:lambda:eu-west-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'eu-west-2': 'arn:aws:lambda:eu-west-2:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'eu-west-3': 'arn:aws:lambda:eu-west-3:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'sa-east-1': 'arn:aws:lambda:sa-east-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'us-east-1': 'arn:aws:lambda:us-east-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'us-east-2': 'arn:aws:lambda:us-east-2:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'us-west-1': 'arn:aws:lambda:us-west-1:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + 'us-west-2': 'arn:aws:lambda:us-west-2:901920570463:layer:aws-otel-collector-arm64-ver-0-70-0:4', + }, + }, '0.68.0': { x86_64: { 'ap-northeast-1': 'arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-collector-amd64-ver-0-68-0:1', diff --git a/packages/@aws-cdk/triggers/package.json b/packages/@aws-cdk/triggers/package.json index 05d426c268df8..0fcc8c783120a 100644 --- a/packages/@aws-cdk/triggers/package.json +++ b/packages/@aws-cdk/triggers/package.json @@ -78,7 +78,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2", "jest": "^27.5.1" diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index bfc20cc70e174..5a5c4ef436d66 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -114,8 +114,8 @@ "punycode": "^2.3.0", "semver": "^7.3.8", "yaml": "1.10.2", - "@aws-cdk/asset-awscli-v1": "^2.2.69", - "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.58", + "@aws-cdk/asset-awscli-v1": "^2.2.85", + "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.71", "@aws-cdk/asset-kubectl-v20": "^2.1.1" }, "devDependencies": { @@ -380,7 +380,7 @@ "@aws-cdk/triggers": "0.0.0", "@aws-cdk/ubergen": "0.0.0", "constructs": "^10.0.0", - "esbuild": "^0.17.8", + "esbuild": "^0.17.10", "fs-extra": "^9.1.0", "ts-node": "^9.1.1", "typescript": "~3.8.3" diff --git a/packages/aws-cdk/THIRD_PARTY_LICENSES b/packages/aws-cdk/THIRD_PARTY_LICENSES index 4497b540f5ff9..144889e860f6e 100644 --- a/packages/aws-cdk/THIRD_PARTY_LICENSES +++ b/packages/aws-cdk/THIRD_PARTY_LICENSES @@ -1,6 +1,6 @@ The aws-cdk package includes the following third-party software/licensing: -** @jsii/check-node@1.75.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.75.0 | Apache-2.0 +** @jsii/check-node@1.76.0 - https://www.npmjs.com/package/@jsii/check-node/v/1.76.0 | Apache-2.0 jsii Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -268,7 +268,7 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH RE ---------------- -** aws-sdk@2.1317.0 - https://www.npmjs.com/package/aws-sdk/v/2.1317.0 | Apache-2.0 +** aws-sdk@2.1325.0 - https://www.npmjs.com/package/aws-sdk/v/2.1325.0 | Apache-2.0 AWS SDK for JavaScript Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -2475,7 +2475,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------- -** raw-body@2.5.1 - https://www.npmjs.com/package/raw-body/v/2.5.1 | MIT +** raw-body@2.5.2 - https://www.npmjs.com/package/raw-body/v/2.5.2 | MIT The MIT License (MIT) Copyright (c) 2013-2014 Jonathan Ong @@ -2545,7 +2545,7 @@ IN THE SOFTWARE. ---------------- -** readable-stream@2.3.7 - https://www.npmjs.com/package/readable-stream/v/2.3.7 | MIT +** readable-stream@2.3.8 - https://www.npmjs.com/package/readable-stream/v/2.3.8 | MIT Node.js is licensed for use as follows: """ @@ -2597,7 +2597,7 @@ IN THE SOFTWARE. ---------------- -** readable-stream@3.6.0 - https://www.npmjs.com/package/readable-stream/v/3.6.0 | MIT +** readable-stream@3.6.1 - https://www.npmjs.com/package/readable-stream/v/3.6.1 | MIT Node.js is licensed for use as follows: """ diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts index e02767b50cc90..a60ab815562b4 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-environment.ts @@ -139,16 +139,26 @@ export class Bootstrapper { * - the name indicating the custom permissions boundary to be used * Re-bootstrapping will NOT be blocked by either tightening or relaxing the permissions' boundary. */ - const currentPermissionsBoundary = current.parameters.InputPermissionsBoundary; + + // InputPermissionsBoundary is an `any` type and if it is not defined it + // appears as an empty string ''. We need to force it to evaluate an empty string + // as undefined + const currentPermissionsBoundary: string | undefined = current.parameters.InputPermissionsBoundary || undefined; const inputPolicyName = params.examplePermissionsBoundary ? CDK_BOOTSTRAP_PERMISSIONS_BOUNDARY : params.customPermissionsBoundary; - let policyName; + let policyName: string | undefined; if (inputPolicyName) { // If the example policy is not already in place, it must be created. const sdk = (await sdkProvider.forEnvironment(environment, Mode.ForWriting)).sdk; policyName = await this.getPolicyName(environment, sdk, inputPolicyName, partition, params); } if (currentPermissionsBoundary !== policyName) { - warning(`Switching from ${currentPermissionsBoundary} to ${policyName} as permissions boundary`); + if (!currentPermissionsBoundary) { + warning(`Adding new permissions boundary ${policyName}`); + } else if (!policyName) { + warning(`Removing existing permissions boundary ${currentPermissionsBoundary}`); + } else { + warning(`Changing permissions boundary from ${currentPermissionsBoundary} to ${policyName}`); + } } return current.update( diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts b/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts index 1d28a442e8ea1..afc05e41c1888 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts @@ -5,6 +5,12 @@ export const REPOSITORY_NAME_OUTPUT = 'RepositoryName'; export const BUCKET_DOMAIN_NAME_OUTPUT = 'BucketDomainName'; export const BOOTSTRAP_VERSION_OUTPUT = 'BootstrapVersion'; export const BOOTSTRAP_VERSION_RESOURCE = 'CdkBootstrapVersion'; +export const BOOTSTRAP_VARIANT_PARAMETER = 'BootstrapVariant'; + +/** + * The assumed vendor of a template in case it is not set + */ +export const DEFAULT_BOOTSTRAP_VARIANT = 'AWS CDK: Default Resources'; /** * Options for the bootstrapEnvironment operation(s) diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml index e5461d63d5fdd..88a5ef4409ce3 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml @@ -50,6 +50,12 @@ Parameters: Default: 'false' AllowedValues: [ 'true', 'false' ] Type: String + BootstrapVariant: + Type: String + Default: 'AWS CDK: Default Resources' + Description: Describe the provenance of the resources in this bootstrap + stack. Change this when you customize the template. To prevent accidents, + the CDK CLI will not overwrite bootstrap stacks with a different variant. Conditions: HasTrustedAccounts: Fn::Not: diff --git a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts index 74f6b7142e66c..684b9ce1e709d 100644 --- a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts +++ b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts @@ -3,7 +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 * as fs from 'fs-extra'; -import { BOOTSTRAP_VERSION_OUTPUT, BootstrapEnvironmentOptions, BOOTSTRAP_VERSION_RESOURCE } from './bootstrap-props'; +import { BOOTSTRAP_VERSION_OUTPUT, BootstrapEnvironmentOptions, BOOTSTRAP_VERSION_RESOURCE, BOOTSTRAP_VARIANT_PARAMETER, DEFAULT_BOOTSTRAP_VARIANT } from './bootstrap-props'; import * as logging from '../../logging'; import { Mode, SdkProvider, ISDK } from '../aws-auth'; import { deployStack, DeployStackResult } from '../deploy-stack'; @@ -63,21 +63,34 @@ export class BootstrapStack { parameters: Record, options: Omit, ): Promise { - - const newVersion = bootstrapVersionFromTemplate(template); - if (this.currentToolkitInfo.found && newVersion < this.currentToolkitInfo.version && !options.force) { - logging.warning(`Bootstrap stack already at version '${this.currentToolkitInfo.version}'. Not downgrading it to version '${newVersion}' (use --force if you intend to downgrade)`); - if (newVersion === 0) { - // A downgrade with 0 as target version means we probably have a new-style bootstrap in the account, - // and an old-style bootstrap as current target, which means the user probably forgot to put this flag in. - logging.warning('(Did you set the \'@aws-cdk/core:newStyleStackSynthesis\' feature flag in cdk.json?)'); - } - - return { + if (this.currentToolkitInfo.found && !options.force) { + // Safety checks + const abortResponse = { noOp: true, outputs: {}, stackArn: this.currentToolkitInfo.bootstrapStack.stackId, }; + + // Validate that the bootstrap stack we're trying to replace is from the same variant as the one we're trying to deploy + const currentVariant = this.currentToolkitInfo.variant; + const newVariant = bootstrapVariantFromTemplate(template); + if (currentVariant !== newVariant) { + logging.warning(`Bootstrap stack already exists, containing '${currentVariant}'. Not overwriting it with a template containing '${newVariant}' (use --force if you intend to overwrite)`); + return abortResponse; + } + + // Validate that we're not downgrading the bootstrap stack + const newVersion = bootstrapVersionFromTemplate(template); + const currentVersion = this.currentToolkitInfo.version; + if (newVersion < currentVersion) { + logging.warning(`Bootstrap stack already at version ${currentVersion}. Not downgrading it to version ${newVersion} (use --force if you intend to downgrade)`); + if (newVersion === 0) { + // A downgrade with 0 as target version means we probably have a new-style bootstrap in the account, + // and an old-style bootstrap as current target, which means the user probably forgot to put this flag in. + logging.warning('(Did you set the \'@aws-cdk/core:newStyleStackSynthesis\' feature flag in cdk.json?)'); + } + return abortResponse; + } } const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap')); @@ -127,3 +140,7 @@ export function bootstrapVersionFromTemplate(template: any): number { } return 0; } + +export function bootstrapVariantFromTemplate(template: any): string { + return template.Parameters?.[BOOTSTRAP_VARIANT_PARAMETER]?.Default ?? DEFAULT_BOOTSTRAP_VARIANT; +} diff --git a/packages/aws-cdk/lib/api/toolkit-info.ts b/packages/aws-cdk/lib/api/toolkit-info.ts index 87a772e5253aa..a2b1b7fd0abc1 100644 --- a/packages/aws-cdk/lib/api/toolkit-info.ts +++ b/packages/aws-cdk/lib/api/toolkit-info.ts @@ -1,7 +1,7 @@ import * as cxapi from '@aws-cdk/cx-api'; import * as chalk from 'chalk'; import { ISDK } from './aws-auth'; -import { BOOTSTRAP_VERSION_OUTPUT, BUCKET_DOMAIN_NAME_OUTPUT, BUCKET_NAME_OUTPUT } from './bootstrap/bootstrap-props'; +import { BOOTSTRAP_VERSION_OUTPUT, BUCKET_DOMAIN_NAME_OUTPUT, BUCKET_NAME_OUTPUT, BOOTSTRAP_VARIANT_PARAMETER, DEFAULT_BOOTSTRAP_VARIANT } from './bootstrap/bootstrap-props'; import { stabilizeStack, CloudFormationStack } from './util/cloudformation'; import { debug, warning } from '../logging'; @@ -102,6 +102,7 @@ export abstract class ToolkitInfo { public abstract readonly bucketUrl: string; public abstract readonly bucketName: string; public abstract readonly version: number; + public abstract readonly variant: string; public abstract readonly bootstrapStack: CloudFormationStack; constructor(protected readonly sdk: ISDK) { @@ -132,6 +133,10 @@ class ExistingToolkitInfo extends ToolkitInfo { return parseInt(this.bootstrapStack.outputs[BOOTSTRAP_VERSION_OUTPUT] ?? '0', 10); } + public get variant() { + return this.bootstrapStack.parameters[BOOTSTRAP_VARIANT_PARAMETER] ?? DEFAULT_BOOTSTRAP_VARIANT; + } + public get parameters(): Record { return this.bootstrapStack.parameters ?? {}; } @@ -258,6 +263,10 @@ class BootstrapStackNotFoundInfo extends ToolkitInfo { throw new Error(this.errorMessage); } + public get variant(): string { + throw new Error(this.errorMessage); + } + public async validateVersion(expectedVersion: number, ssmParameterName: string | undefined): Promise { if (ssmParameterName === undefined) { throw new Error(this.errorMessage); diff --git a/packages/aws-cdk/lib/init-templates/app/csharp/README.md b/packages/aws-cdk/lib/init-templates/app/csharp/README.md index d2eb4e9e33144..f28e4d55306cb 100644 --- a/packages/aws-cdk/lib/init-templates/app/csharp/README.md +++ b/packages/aws-cdk/lib/init-templates/app/csharp/README.md @@ -4,7 +4,7 @@ This is a blank project for CDK development with C#. The `cdk.json` file tells the CDK Toolkit how to execute your app. -It uses the [.NET Core CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. +It uses the [.NET CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. ## Useful commands diff --git a/packages/aws-cdk/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj b/packages/aws-cdk/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj index a839c9651027a..e82ee424f2b6c 100644 --- a/packages/aws-cdk/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +++ b/packages/aws-cdk/lib/init-templates/app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 Major diff --git a/packages/aws-cdk/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj b/packages/aws-cdk/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj index e28dbb84b14a1..07755869f787b 100644 --- a/packages/aws-cdk/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +++ b/packages/aws-cdk/lib/init-templates/app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 Major diff --git a/packages/aws-cdk/lib/init-templates/app/javascript/package.json b/packages/aws-cdk/lib/init-templates/app/javascript/package.json index 25f9cd9a79e94..3d4f898b31c6b 100644 --- a/packages/aws-cdk/lib/init-templates/app/javascript/package.json +++ b/packages/aws-cdk/lib/init-templates/app/javascript/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "aws-cdk": "%cdk-version%", - "jest": "^29.4.2" + "jest": "^29.4.3" }, "dependencies": { "aws-cdk-lib": "%cdk-version%", diff --git a/packages/aws-cdk/lib/init-templates/app/typescript/package.json b/packages/aws-cdk/lib/init-templates/app/typescript/package.json index 08a087dd655c1..c2d4c49eb5f5f 100644 --- a/packages/aws-cdk/lib/init-templates/app/typescript/package.json +++ b/packages/aws-cdk/lib/init-templates/app/typescript/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "@types/jest": "^29.4.0", - "@types/node": "18.13.0", - "jest": "^29.4.2", + "@types/node": "18.14.2", + "jest": "^29.4.3", "ts-jest": "^29.0.5", "aws-cdk": "%cdk-version%", "ts-node": "^10.9.1", diff --git a/packages/aws-cdk/lib/init-templates/lib/typescript/package.json b/packages/aws-cdk/lib/init-templates/lib/typescript/package.json index 130562ff49e73..ddfbc0ba961ab 100644 --- a/packages/aws-cdk/lib/init-templates/lib/typescript/package.json +++ b/packages/aws-cdk/lib/init-templates/lib/typescript/package.json @@ -10,10 +10,10 @@ }, "devDependencies": { "@types/jest": "^29.4.0", - "@types/node": "18.13.0", + "@types/node": "18.14.2", "aws-cdk-lib": "%cdk-version%", "constructs": "%constructs-version%", - "jest": "^29.4.2", + "jest": "^29.4.3", "ts-jest": "^29.0.5", "typescript": "~4.9.5" }, diff --git a/packages/aws-cdk/lib/init-templates/sample-app/csharp/README.template.md b/packages/aws-cdk/lib/init-templates/sample-app/csharp/README.template.md index 411d4e653994e..829e5976af869 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/csharp/README.template.md +++ b/packages/aws-cdk/lib/init-templates/sample-app/csharp/README.template.md @@ -5,7 +5,7 @@ which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic. The `cdk.json` file tells the CDK Toolkit how to execute your app. -It uses the [.NET Core CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. +It uses the [.NET CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. ## Useful commands diff --git a/packages/aws-cdk/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj b/packages/aws-cdk/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj index a839c9651027a..e82ee424f2b6c 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj +++ b/packages/aws-cdk/lib/init-templates/sample-app/csharp/src/%name.PascalCased%/%name.PascalCased%.template.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 Major diff --git a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/README.template.md b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/README.template.md index d1bfcf9a90ccf..71d05a9cdeb27 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/README.template.md +++ b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/README.template.md @@ -6,7 +6,7 @@ which contains an Amazon SQS queue that is subscribed to an Amazon SNS topic. The `cdk.json` file tells the CDK Toolkit how to execute your app. -It uses the [.NET Core CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. +It uses the [.NET CLI](https://docs.microsoft.com/dotnet/articles/core/) to compile and execute your project. ## Useful commands diff --git a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj index e28dbb84b14a1..07755869f787b 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj +++ b/packages/aws-cdk/lib/init-templates/sample-app/fsharp/src/%name.PascalCased%/%name.PascalCased%.template.fsproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 Major diff --git a/packages/aws-cdk/lib/init-templates/sample-app/javascript/package.json b/packages/aws-cdk/lib/init-templates/sample-app/javascript/package.json index 25f9cd9a79e94..3d4f898b31c6b 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/javascript/package.json +++ b/packages/aws-cdk/lib/init-templates/sample-app/javascript/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "aws-cdk": "%cdk-version%", - "jest": "^29.4.2" + "jest": "^29.4.3" }, "dependencies": { "aws-cdk-lib": "%cdk-version%", diff --git a/packages/aws-cdk/lib/init-templates/sample-app/typescript/package.json b/packages/aws-cdk/lib/init-templates/sample-app/typescript/package.json index f2df4136e89d2..3c82377faa1c2 100644 --- a/packages/aws-cdk/lib/init-templates/sample-app/typescript/package.json +++ b/packages/aws-cdk/lib/init-templates/sample-app/typescript/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "@types/jest": "^29.4.0", - "@types/node": "18.13.0", - "jest": "^29.4.2", + "@types/node": "18.14.2", + "jest": "^29.4.3", "ts-jest": "^29.0.5", "aws-cdk": "%cdk-version%", "ts-node": "^10.9.1", diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index bfb389e4204f9..00f0dc12be4f3 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -98,9 +98,9 @@ "@aws-cdk/cloudformation-diff": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", - "@jsii/check-node": "1.75.0", + "@jsii/check-node": "1.76.0", "archiver": "^5.3.1", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "camelcase": "^6.3.0", "cdk-assets": "0.0.0", "chokidar": "^3.5.3", diff --git a/packages/aws-cdk/test/api/bootstrap2.test.ts b/packages/aws-cdk/test/api/bootstrap2.test.ts index 5ca8b6e3f9929..bedd4f968c2e5 100644 --- a/packages/aws-cdk/test/api/bootstrap2.test.ts +++ b/packages/aws-cdk/test/api/bootstrap2.test.ts @@ -12,9 +12,15 @@ import { mockBootstrapStack, MockSdk, MockSdkProvider } from '../util/mock-sdk'; let bootstrapper: Bootstrapper; let mockGetPolicyIamCode: (params: IAM.Types.GetPolicyRequest) => IAM.Types.GetPolicyResponse; let mockCreatePolicyIamCode: (params: IAM.Types.CreatePolicyRequest) => IAM.Types.CreatePolicyResponse; +let stderrMock: jest.SpyInstance; beforeEach(() => { bootstrapper = new Bootstrapper({ source: 'default' }); + stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; }); +}); + +afterEach(() => { + stderrMock.mockRestore(); }); function mockTheToolkitInfo(stackProps: Partial) { @@ -114,6 +120,14 @@ describe('Bootstrapping v2', () => { }); test('passes value to PermissionsBoundary', async () => { + mockTheToolkitInfo({ + Parameters: [ + { + ParameterKey: 'InputPermissionsBoundary', + ParameterValue: 'existing-pb', + }, + ], + }); await bootstrapper.bootstrapEnvironment(env, sdk, { parameters: { customPermissionsBoundary: 'permissions-boundary-name', @@ -125,6 +139,71 @@ describe('Bootstrapping v2', () => { InputPermissionsBoundary: 'permissions-boundary-name', }), })); + expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([ + expect.arrayContaining([ + expect.stringMatching(/Changing permissions boundary from existing-pb to permissions-boundary-name/), + ]), + ])); + }); + + test('permission boundary switch message does not appear', async () => { + mockTheToolkitInfo({ + Parameters: [ + { + ParameterKey: 'InputPermissionsBoundary', + ParameterValue: '', + }, + ], + }); + await bootstrapper.bootstrapEnvironment(env, sdk); + + expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([ + expect.not.arrayContaining([ + expect.stringMatching(/Changing permissions boundary/), + ]), + ])); + }); + + test('adding new permissions boundary', async () => { + mockTheToolkitInfo({ + Parameters: [ + { + ParameterKey: 'InputPermissionsBoundary', + ParameterValue: '', + }, + ], + }); + await bootstrapper.bootstrapEnvironment(env, sdk, { + parameters: { + customPermissionsBoundary: 'permissions-boundary-name', + }, + }); + + expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([ + expect.arrayContaining([ + expect.stringMatching(/Adding new permissions boundary permissions-boundary-name/), + ]), + ])); + }); + + test('removing existing permissions boundary', async () => { + mockTheToolkitInfo({ + Parameters: [ + { + ParameterKey: 'InputPermissionsBoundary', + ParameterValue: 'permissions-boundary-name', + }, + ], + }); + await bootstrapper.bootstrapEnvironment(env, sdk, { + parameters: {}, + }); + + expect(stderrMock.mock.calls).toEqual(expect.arrayContaining([ + expect.arrayContaining([ + expect.stringMatching(/Removing existing permissions boundary permissions-boundary-name/), + ]), + ])); }); test('passing trusted accounts without CFN managed policies results in an error', async () => { @@ -220,6 +299,21 @@ describe('Bootstrapping v2', () => { })).resolves.toEqual(expect.objectContaining({ noOp: true })); }); + test('Do not allow overwriting bootstrap stack from a different vendor', async () => { + // GIVEN + mockTheToolkitInfo({ + Parameters: [ + { + ParameterKey: 'BootstrapVariant', + ParameterValue: 'JoeSchmoe', + }, + ], + }); + + await expect(bootstrapper.bootstrapEnvironment(env, sdk, { + })).resolves.toEqual(expect.objectContaining({ noOp: true })); + }); + test('bootstrap template has the right exports', async () => { let template: any; mockDeployStack.mockImplementation((args: DeployStackOptions) => { diff --git a/packages/aws-cdk/test/api/cloudformation-deployments.test.ts b/packages/aws-cdk/test/api/cloudformation-deployments.test.ts index 97278ffd3e8a8..40cc63e2edf68 100644 --- a/packages/aws-cdk/test/api/cloudformation-deployments.test.ts +++ b/packages/aws-cdk/test/api/cloudformation-deployments.test.ts @@ -8,6 +8,7 @@ import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import { CloudFormation } from 'aws-sdk'; import { FakeCloudformationStack } from './fake-cloudformation-stack'; +import { DEFAULT_BOOTSTRAP_VARIANT } from '../../lib'; import { CloudFormationDeployments } from '../../lib/api/cloudformation-deployments'; import { deployStack } from '../../lib/api/deploy-stack'; import { HotswapMode } from '../../lib/api/hotswap/common'; @@ -931,6 +932,7 @@ function testStackWithAssetManifest() { public found: boolean = true; public bucketUrl: string = 's3://fake/here'; public bucketName: string = 'fake'; + public variant: string = DEFAULT_BOOTSTRAP_VARIANT; public version: number = 1234; public get bootstrapStack(): CloudFormationStack { throw new Error('This should never happen'); @@ -1000,4 +1002,4 @@ function testStackWithAssetManifest() { const assembly = builder.buildAssembly(); return assembly.getStackArtifact('stack'); -} \ No newline at end of file +} diff --git a/packages/aws-cdk/test/init.test.ts b/packages/aws-cdk/test/init.test.ts index 79af055608578..4ecdc53789530 100644 --- a/packages/aws-cdk/test/init.test.ts +++ b/packages/aws-cdk/test/init.test.ts @@ -58,6 +58,7 @@ describe('constructs version', () => { const sln = (await fs.readFile(slnFile, 'utf8')).split(/\r?\n/); expect(csproj).toContainEqual(expect.stringMatching(/\net6.0<\/TargetFramework>/)); expect(sln).toContainEqual(expect.stringMatching(/\"AwsCdkTest[a-zA-Z0-9]{6}\\AwsCdkTest[a-zA-Z0-9]{6}.csproj\"/)); }); @@ -73,6 +74,7 @@ describe('constructs version', () => { const sln = (await fs.readFile(slnFile, 'utf8')).split(/\r?\n/); expect(fsproj).toContainEqual(expect.stringMatching(/\net6.0<\/TargetFramework>/)); expect(sln).toContainEqual(expect.stringMatching(/\"AwsCdkTest[a-zA-Z0-9]{6}\\AwsCdkTest[a-zA-Z0-9]{6}.fsproj\"/)); }); @@ -85,6 +87,7 @@ describe('constructs version', () => { const csproj = (await fs.readFile(csprojFile, 'utf8')).split(/\r?\n/); expect(csproj).toContainEqual(expect.stringMatching(/\net6.0<\/TargetFramework>/)); }); cliTestWithDirSpaces('fsharp app with spaces', async (workDir) => { @@ -96,6 +99,7 @@ describe('constructs version', () => { const fsproj = (await fs.readFile(fsprojFile, 'utf8')).split(/\r?\n/); expect(fsproj).toContainEqual(expect.stringMatching(/\net6.0<\/TargetFramework>/)); }); cliTest('create a Python app project', async (workDir) => { diff --git a/packages/aws-cdk/test/integ/init/test-go-app.sh b/packages/aws-cdk/test/integ/init/test-go-app.sh old mode 100644 new mode 100755 diff --git a/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh b/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh index c735580c9fd58..b8d3684c70ba6 100755 --- a/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh +++ b/packages/aws-cdk/test/integ/test-cli-regression-against-current-code.sh @@ -9,4 +9,4 @@ previous=$(${INTEG_TOOLS}/bin/query-github last-release --token $GITHUB_TOKEN -- echo "Previous version is: $previous" # Old tests, new CLI, new framework -exec $INTEG_TOOLS/bin/download-and-run-old-tests "$previous" --use-cli-release=$VERSION cli-integ-tests +exec $INTEG_TOOLS/bin/download-and-run-old-tests "$previous" --regression --use-cli-release=$VERSION cli-integ-tests diff --git a/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh b/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh index 8c828fb2138ce..854eb047c06b9 100755 --- a/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh +++ b/packages/aws-cdk/test/integ/test-cli-regression-against-latest-release.sh @@ -8,4 +8,4 @@ previous=$(${INTEG_TOOLS}/bin/query-github last-release --token $GITHUB_TOKEN -- echo "Previous version is: $previous" # Old tests, new CLI, old framework -exec $INTEG_TOOLS/bin/download-and-run-old-tests "$previous" --use-cli-release=$VERSION --framework-version=$previous cli-integ-tests +exec $INTEG_TOOLS/bin/download-and-run-old-tests "$previous" --regression --use-cli-release=$VERSION --framework-version=$previous cli-integ-tests diff --git a/packages/aws-cdk/test/util/mock-toolkitinfo.ts b/packages/aws-cdk/test/util/mock-toolkitinfo.ts index f86e7fec94965..e46054e5a5d4a 100644 --- a/packages/aws-cdk/test/util/mock-toolkitinfo.ts +++ b/packages/aws-cdk/test/util/mock-toolkitinfo.ts @@ -1,4 +1,4 @@ -import { ISDK, ToolkitInfo } from '../../lib/api'; +import { ISDK, ToolkitInfo, DEFAULT_BOOTSTRAP_VARIANT } from '../../lib/api'; import { CloudFormationStack } from '../../lib/api/util/cloudformation'; export interface MockToolkitInfoProps { @@ -17,6 +17,7 @@ export class MockToolkitInfo extends ToolkitInfo { public readonly bucketUrl: string; public readonly bucketName: string; public readonly version: number; + public readonly variant: string; public readonly prepareEcrRepository = mockLike(); private readonly _bootstrapStack?: CloudFormationStack; @@ -27,6 +28,7 @@ export class MockToolkitInfo extends ToolkitInfo { this.bucketName = props.bucketName ?? 'MockToolkitBucketName'; this.bucketUrl = props.bucketUrl ?? `https://${this.bucketName}.s3.amazonaws.com/`; this.version = props.version ?? 1; + this.variant = DEFAULT_BOOTSTRAP_VARIANT; this._bootstrapStack = props.bootstrapStack; } diff --git a/packages/awslint/package.json b/packages/awslint/package.json index eabb892dae50e..fd31ed7b098e7 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -18,11 +18,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "1.75.0", + "@jsii/spec": "1.76.0", "camelcase": "^6.3.0", "chalk": "^4", "fs-extra": "^9.1.0", - "jsii-reflect": "1.75.0", + "jsii-reflect": "1.76.0", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/cdk-assets/lib/private/docker.ts b/packages/cdk-assets/lib/private/docker.ts index 7cca00a2d0cbd..509e15cbed22f 100644 --- a/packages/cdk-assets/lib/private/docker.ts +++ b/packages/cdk-assets/lib/private/docker.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { cdkCredentialsConfig, obtainEcrCredentials } from './docker-credentials'; -import { Logger, shell, ShellOptions } from './shell'; +import { Logger, shell, ShellOptions, ProcessFailedError } from './shell'; import { createCriticalSection } from './util'; interface BuildOptions { @@ -31,6 +31,11 @@ export interface DockerDomainCredentials { readonly ecrRepository?: string; } +enum InspectImageErrorCode { + Docker = 1, + Podman = 125 +} + export class Docker { private configDir: string | undefined = undefined; @@ -46,8 +51,31 @@ export class Docker { await this.execute(['inspect', tag], { quiet: true }); return true; } catch (e) { - if (e.code !== 'PROCESS_FAILED' || e.exitCode !== 1) { throw e; } - return false; + const error: ProcessFailedError = e; + + /** + * The only error we expect to be thrown will have this property and value. + * If it doesn't, it's unrecognized so re-throw it. + */ + if (error.code !== 'PROCESS_FAILED') { + throw error; + } + + /** + * If we know the shell command above returned an error, check to see + * if the exit code is one we know to actually mean that the image doesn't + * exist. + */ + switch (error.exitCode) { + case InspectImageErrorCode.Docker: + case InspectImageErrorCode.Podman: + // Docker and Podman will return this exit code when an image doesn't exist, return false + // context: https://github.com/aws/aws-cdk/issues/16209 + return false; + default: + // This is an error but it's not an exit code we recognize, throw. + throw error; + } } } diff --git a/packages/cdk-assets/lib/private/shell.ts b/packages/cdk-assets/lib/private/shell.ts index 46eb7c6c571e1..ba7837f49810e 100644 --- a/packages/cdk-assets/lib/private/shell.ts +++ b/packages/cdk-assets/lib/private/shell.ts @@ -61,6 +61,8 @@ export async function shell(command: string[], options: ShellOptions = {}): Prom }); } +export type ProcessFailedError = ProcessFailed + class ProcessFailed extends Error { public readonly code = 'PROCESS_FAILED'; diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index a192f79aa6139..be2a4e69f3df4 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -46,7 +46,7 @@ "@aws-cdk/cloud-assembly-schema": "0.0.0", "@aws-cdk/cx-api": "0.0.0", "archiver": "^5.3.1", - "aws-sdk": "^2.1317.0", + "aws-sdk": "^2.1325.0", "glob": "^7.2.3", "mime": "^2.6.0", "yargs": "^16.2.0" diff --git a/packages/cdk-assets/test/private/docker.test.ts b/packages/cdk-assets/test/private/docker.test.ts new file mode 100644 index 0000000000000..40c37ca35f271 --- /dev/null +++ b/packages/cdk-assets/test/private/docker.test.ts @@ -0,0 +1,94 @@ +import { Docker } from '../../lib/private/docker'; +import { ShellOptions, ProcessFailedError } from '../../lib/private/shell'; + +type ShellExecuteMock = jest.SpyInstance, Parameters>; + +describe('Docker', () => { + describe('exists', () => { + let docker: Docker; + + const makeShellExecuteMock = ( + fn: (params: string[]) => void, + ): ShellExecuteMock => + jest.spyOn<{ execute: Docker['execute'] }, 'execute'>(Docker.prototype as any, 'execute').mockImplementation( + async (params: string[], _options?: ShellOptions) => fn(params), + ); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + beforeEach(() => { + docker = new Docker(); + }); + + test('returns true when image inspect command does not throw', async () => { + const spy = makeShellExecuteMock(() => undefined); + + const imageExists = await docker.exists('foo'); + + expect(imageExists).toBe(true); + expect(spy.mock.calls[0][0]).toEqual(['inspect', 'foo']); + }); + + test('throws when an arbitrary error is caught', async () => { + makeShellExecuteMock(() => { + throw new Error(); + }); + + await expect(docker.exists('foo')).rejects.toThrow(); + }); + + test('throws when the error is a shell failure but the exit code is unrecognized', async () => { + makeShellExecuteMock(() => { + throw new (class extends Error implements ProcessFailedError { + public readonly code = 'PROCESS_FAILED' + public readonly exitCode = 47 + public readonly signal = null + + constructor() { + super('foo'); + } + }); + }); + + await expect(docker.exists('foo')).rejects.toThrow(); + }); + + test('returns false when the error is a shell failure and the exit code is 1 (Docker)', async () => { + makeShellExecuteMock(() => { + throw new (class extends Error implements ProcessFailedError { + public readonly code = 'PROCESS_FAILED' + public readonly exitCode = 1 + public readonly signal = null + + constructor() { + super('foo'); + } + }); + }); + + const imageExists = await docker.exists('foo'); + + expect(imageExists).toBe(false); + }); + + test('returns false when the error is a shell failure and the exit code is 125 (Podman)', async () => { + makeShellExecuteMock(() => { + throw new (class extends Error implements ProcessFailedError { + public readonly code = 'PROCESS_FAILED' + public readonly exitCode = 125 + public readonly signal = null + + constructor() { + super('foo'); + } + }); + }); + + const imageExists = await docker.exists('foo'); + + expect(imageExists).toBe(false); + }); + }); +}); diff --git a/packages/cdk-dasm/package.json b/packages/cdk-dasm/package.json index 862919c7cabbd..0b9f1def89778 100644 --- a/packages/cdk-dasm/package.json +++ b/packages/cdk-dasm/package.json @@ -30,7 +30,7 @@ }, "license": "Apache-2.0", "dependencies": { - "codemaker": "1.75.0", + "codemaker": "1.76.0", "yaml": "1.10.2" }, "devDependencies": { diff --git a/scripts/check-build-prerequisites.sh b/scripts/check-build-prerequisites.sh index d90b5d76b73b4..93f9606e7c52e 100755 --- a/scripts/check-build-prerequisites.sh +++ b/scripts/check-build-prerequisites.sh @@ -121,13 +121,13 @@ else fi fi -# [.NET == 3.1.x, == 5.x] +# [.NET == 6.0.x] app="dotnet" -app_min="3.1.0" +app_min="6.0.100" check_which $app $app_min app_v=$(${app} --list-sdks) echo -e "Checking dotnet version... \c" -if [ $(echo $app_v | grep -c -E "(3\.1\.[0-9]+|[5-7]\.[0-9]+\.[0-9]+)") -eq 1 ] +if [ $(echo $app_v | grep -c -E "6\.[0-9]+\.[0-9]+") -eq 1 ] then echo "Ok" else diff --git a/scripts/check-pack-prerequisites.sh b/scripts/check-pack-prerequisites.sh index 01eb0fce515b0..30f42ad4b24e5 100755 --- a/scripts/check-pack-prerequisites.sh +++ b/scripts/check-pack-prerequisites.sh @@ -79,13 +79,13 @@ else wrong_version fi -# [.NET Core SDK 3.1.*] +# [.NET SDK 6.0.*] app="dotnet" -app_min="3.1.0" +app_min="6.0.100" check_which $app $app_min app_v=$(${app} --list-sdks) echo -e "Checking $app version... \c" -if [ $(echo $app_v | grep -c -E "3\.1\.[0-9].*|[4-9]\..*") -eq 1 ] +if [ $(echo $app_v | grep -c -E "6\.0\.[0-9].*|[4-9]\..*") -eq 1 ] then echo "Ok" else diff --git a/tests.txt b/tests.txt index a926eafe89f4c..d399caf54e906 100644 --- a/tests.txt +++ b/tests.txt @@ -210,7 +210,6 @@ aws-dynamodb/test/integ.dynamodb.ondemand.js aws-dynamodb/test/integ.dynamodb.sse.js aws-dynamodb/test/integ.global-replicas-provisioned.js aws-dynamodb/test/integ.global.js -aws-dynamodb-global/test/integ.dynamodb.global.js aws-ec2/test/integ.bastion-host-arm-support.js aws-ec2/test/integ.bastion-host.js aws-ec2/test/integ.client-vpn-endpoint.js diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index fdf0692ee8235..b8ed716059491 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -57,9 +57,9 @@ "fs-extra": "^9.1.0", "jest": "^27.5.1", "jest-junit": "^13.2.0", - "jsii": "1.75.0", - "jsii-pacmak": "1.75.0", - "jsii-reflect": "1.75.0", + "jsii": "1.76.0", + "jsii-pacmak": "1.76.0", + "jsii-reflect": "1.76.0", "markdownlint-cli": "^0.33.0", "nyc": "^15.1.0", "semver": "^7.3.8", diff --git a/tools/@aws-cdk/cfn2ts/package.json b/tools/@aws-cdk/cfn2ts/package.json index 3f8ee3623f90b..73eebbefafe61 100644 --- a/tools/@aws-cdk/cfn2ts/package.json +++ b/tools/@aws-cdk/cfn2ts/package.json @@ -32,7 +32,7 @@ "license": "Apache-2.0", "dependencies": { "@aws-cdk/cfnspec": "0.0.0", - "codemaker": "1.75.0", + "codemaker": "1.76.0", "fast-json-patch": "^3.1.1", "fs-extra": "^9.1.0", "yargs": "^16.2.0" diff --git a/tools/@aws-cdk/node-bundle/package.json b/tools/@aws-cdk/node-bundle/package.json index 57948450adb39..4108e453a5a34 100644 --- a/tools/@aws-cdk/node-bundle/package.json +++ b/tools/@aws-cdk/node-bundle/package.json @@ -40,19 +40,19 @@ "jest-junit": "^13", "json-schema": "^0.4.0", "npm-check-updates": "^12", - "projen": "^0.67.57", + "projen": "^0.67.69", "standard-version": "^9", "ts-jest": "^27", "typescript": "^4.5.5" }, "dependencies": { - "cdk-generate-synthetic-examples": "^0.1.155", - "esbuild": "^0.17.8", + "cdk-generate-synthetic-examples": "^0.1.167", + "esbuild": "^0.17.10", "fs-extra": "^10.1.0", "license-checker": "^25.0.1", "madge": "^5.0.2", "shlex": "^2.1.2", - "yargs": "^17.7.0" + "yargs": "^17.7.1" }, "main": "lib/index.js", "license": "Apache-2.0", diff --git a/version.v2.json b/version.v2.json index 95ce8e353b069..069c913a7cd3e 100644 --- a/version.v2.json +++ b/version.v2.json @@ -1,4 +1,4 @@ { - "version": "2.66.0", - "alphaVersion": "2.66.0-alpha.0" + "version": "2.66.1", + "alphaVersion": "2.66.1-alpha.0" } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 45da20e8e9130..a8e1c91085beb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27,7 +27,7 @@ dependencies: tunnel "^0.0.6" -"@ampproject/remapping@^2.1.0": +"@ampproject/remapping@^2.2.0": version "2.2.0" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== @@ -35,25 +35,25 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@aws-cdk/asset-awscli-v1@^2.2.69": - version "2.2.69" - resolved "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.69.tgz#8b896adbad686fc8924018dc4a2d81dcea1868d4" - integrity sha512-sKhINBDXKc9cad+4ghBsn6nB63ci7KcO7Vb2FswBI36Z7lkaIkz51pPwmVWn8AsYNOvCpcaCxUx0zngCbQOluQ== +"@aws-cdk/asset-awscli-v1@^2.2.85": + version "2.2.85" + resolved "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.85.tgz#3671dc4de44f243571a806d651697bb4f49d06c1" + integrity sha512-oNX4HMupi2+/blbUNctA8WIwyqFTLOGhGDB+gginMSy7QHevLWb/duMlwa7Np4wpiHeiBDMF/ccc5Mfb352srg== "@aws-cdk/asset-kubectl-v20@^2.1.1": version "2.1.1" resolved "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz#d01c1efb867fb7f2cfd8c8b230b8eae16447e156" integrity sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw== -"@aws-cdk/asset-node-proxy-agent-v5@^2.0.58": - version "2.0.58" - resolved "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.58.tgz#1a8de9fd628306d9a7e93de1b06a0ed424e89502" - integrity sha512-7BTzPo1tBw1tTYEmWNO0nS+bTJ/Ikg2qpFQZBb0GedEJ1v713IyRoySlKADAXAaMPJU9Gg05LCuJy+cs7RUDMQ== +"@aws-cdk/asset-node-proxy-agent-v5@^2.0.71": + version "2.0.71" + resolved "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.71.tgz#dd269f8aa160473e006633d2f0f5384f46747693" + integrity sha512-vB/KF9naAYkELP6Hi5+Oib59B4ZAz6jjtrpsKNzsIZTmcTs0IIBb4nVdAuwMpMkPcwT0mzhMg2tlsiSyjrOFBA== -"@aws-cdk/lambda-layer-kubectl-v24@^2.0.100": - version "2.0.100" - resolved "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v24/-/lambda-layer-kubectl-v24-2.0.100.tgz#c4450e7985f16e048c1041525fa1146866d93eee" - integrity sha512-14svXKODfjR9K8uuVXS8raqtfCLXI6dEUWvBQafiq72GJ33vTycoa3rHalYgj0CLS+pXMERSyUT2NiBDNBG8iA== +"@aws-cdk/lambda-layer-kubectl-v24@^2.0.113": + version "2.0.113" + resolved "https://registry.npmjs.org/@aws-cdk/lambda-layer-kubectl-v24/-/lambda-layer-kubectl-v24-2.0.113.tgz#7b22497eb41bd88cfdea73a34c398721514b72c6" + integrity sha512-8mn6/5s/EDxmQP1cnoIAYqGwHmUl+Jimbnut/7Jhz6MzvmkDU9olpem1W6bESmrI6RFTX/1UABz+jaYthmqlXA== "@babel/code-frame@7.12.11": version "7.12.11" @@ -70,38 +70,39 @@ "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.20.5": - version "7.20.14" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.14.tgz#4106fc8b755f3e3ee0a0a7c27dde5de1d2b2baf8" - integrity sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw== + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz#c241dc454e5b5917e40d37e525e2f4530c399298" + integrity sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g== "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.8.0": - version "7.20.12" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" - integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" + integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== dependencies: - "@ampproject/remapping" "^2.1.0" + "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.0" "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helpers" "^7.20.7" - "@babel/parser" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.0" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.0" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.12" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.2" semver "^6.3.0" -"@babel/generator@^7.20.7", "@babel/generator@^7.7.2": - version "7.20.14" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz#9fa772c9f86a46c6ac9b321039400712b96f64ce" - integrity sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg== +"@babel/generator@^7.21.0", "@babel/generator@^7.21.1", "@babel/generator@^7.7.2": + version "7.21.1" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.21.0" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" "@babel/helper-compilation-targets@^7.20.7": @@ -120,13 +121,13 @@ resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" @@ -142,10 +143,10 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.20.11": - version "7.20.11" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" - integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== +"@babel/helper-module-transforms@^7.21.0": + version "7.21.2" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" + integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" @@ -153,8 +154,8 @@ "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.10" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.2" + "@babel/types" "^7.21.2" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": version "7.20.2" @@ -186,18 +187,18 @@ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" + integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== -"@babel/helpers@^7.20.7": - version "7.20.13" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz#e3cb731fb70dc5337134cadc24cbbad31cc87ad2" - integrity sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg== +"@babel/helpers@^7.21.0": + version "7.21.0" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" + integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== dependencies: "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.13" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": version "7.18.6" @@ -208,10 +209,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.13", "@babel/parser@^7.20.7": - version "7.20.15" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz#eec9f36d8eaf0948bb88c87a46784b5ee9fd0c89" - integrity sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": + version "7.21.2" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" + integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -304,7 +305,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" -"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": +"@babel/template@^7.20.7", "@babel/template@^7.3.3": version "7.20.7" resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== @@ -313,26 +314,26 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13", "@babel/traverse@^7.7.2": - version "7.20.13" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" - integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ== +"@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.7.2": + version "7.21.2" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" + integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.1" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.13" - "@babel/types" "^7.20.7" + "@babel/parser" "^7.21.2" + "@babel/types" "^7.21.2" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.20.7" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.21.2" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" + integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -360,115 +361,115 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@esbuild/android-arm64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz#b3d5b65a3b2e073a6c7ee36b1f3c30c8f000315b" - integrity sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ== - -"@esbuild/android-arm@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz#c41e496af541e175369d48164d0cf01a5f656cf6" - integrity sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w== - -"@esbuild/android-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz#080fa67c29be77f5a3ca5ee4cc78d5bf927e3a3b" - integrity sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg== - -"@esbuild/darwin-arm64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz#053622bf9a82f43d5c075b7818e02618f7b4a397" - integrity sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg== - -"@esbuild/darwin-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz#8a1aadb358d537d8efad817bb1a5bff91b84734b" - integrity sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw== - -"@esbuild/freebsd-arm64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz#e6738d0081ba0721a5c6c674e84c6e7fcea61989" - integrity sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A== - -"@esbuild/freebsd-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz#1855e562f2b730f4483f6e94086e9e2597feb4c3" - integrity sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q== - -"@esbuild/linux-arm64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz#481da38952721a3fdb77c17a36ceaacc4270b5c5" - integrity sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww== - -"@esbuild/linux-arm@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz#18127072b270bb6321c6d11be20bfd30e0d6ad17" - integrity sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA== - -"@esbuild/linux-ia32@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz#ee400af7b3bc69e8ca2e593ca35156ffb9abd54f" - integrity sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA== - -"@esbuild/linux-loong64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz#8c509d8a454693d39824b83b3f66c400872fce82" - integrity sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA== - -"@esbuild/linux-mips64el@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz#f2b0d36e63fb26bc3f95b203b6a80638292101ca" - integrity sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA== - -"@esbuild/linux-ppc64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz#1e628be003e036e90423716028cc884fe5ba25bd" - integrity sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw== - -"@esbuild/linux-riscv64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz#419a815cb4c3fb9f1b78ef5295f5b48b8bf6427a" - integrity sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw== - -"@esbuild/linux-s390x@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz#291c49ae5c3d11d226352755c0835911fe1a9e5c" - integrity sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw== - -"@esbuild/linux-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz#03199d91c76faf80bd54104f5cbf0a489bc39f6a" - integrity sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA== - -"@esbuild/netbsd-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz#b436d767e1b21852f9ed212e2bb57f77203b0ae2" - integrity sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q== - -"@esbuild/openbsd-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz#d1481d8539e21d4729cd04a0450a26c2c8789e89" - integrity sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg== - -"@esbuild/sunos-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz#2cfb8126e079b2c00fd1bf095541e9f5c47877e4" - integrity sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw== - -"@esbuild/win32-arm64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz#7c6ecfd097ca23b82119753bf7072bbaefe51e3a" - integrity sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg== - -"@esbuild/win32-ia32@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz#cffec63c3cb0ef8563a04df4e09fa71056171d00" - integrity sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w== - -"@esbuild/win32-x64@0.17.8": - version "0.17.8" - resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz#200a0965cf654ac28b971358ecdca9cc5b44c335" - integrity sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg== +"@esbuild/android-arm64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.10.tgz#ad2ee47dd021035abdfb0c38848ff77a1e1918c4" + integrity sha512-ht1P9CmvrPF5yKDtyC+z43RczVs4rrHpRqrmIuoSvSdn44Fs1n6DGlpZKdK6rM83pFLbVaSUwle8IN+TPmkv7g== + +"@esbuild/android-arm@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.10.tgz#bb5a68af8adeb94b30eadee7307404dc5237d076" + integrity sha512-7YEBfZ5lSem9Tqpsz+tjbdsEshlO9j/REJrfv4DXgKTt1+/MHqGwbtlyxQuaSlMeUZLxUKBaX8wdzlTfHkmnLw== + +"@esbuild/android-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.10.tgz#751d5d8ae9ece1efa9627b689c888eb85b102360" + integrity sha512-CYzrm+hTiY5QICji64aJ/xKdN70IK8XZ6iiyq0tZkd3tfnwwSWTYH1t3m6zyaaBxkuj40kxgMyj1km/NqdjQZA== + +"@esbuild/darwin-arm64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.10.tgz#85601ee7efb2129cd3218d5bcbe8da1173bc1e8b" + integrity sha512-3HaGIowI+nMZlopqyW6+jxYr01KvNaLB5znXfbyyjuo4lE0VZfvFGcguIJapQeQMS4cX/NEispwOekJt3gr5Dg== + +"@esbuild/darwin-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.10.tgz#362c7e988c61fe72d5edef4f717e4b4fc728da98" + integrity sha512-J4MJzGchuCRG5n+B4EHpAMoJmBeAE1L3wGYDIN5oWNqX0tEr7VKOzw0ymSwpoeSpdCa030lagGUfnfhS7OvzrQ== + +"@esbuild/freebsd-arm64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.10.tgz#e8a85a46ede7c3a048a12f16b9d551d25adc8bb1" + integrity sha512-ZkX40Z7qCbugeK4U5/gbzna/UQkM9d9LNV+Fro8r7HA7sRof5Rwxc46SsqeMvB5ZaR0b1/ITQ/8Y1NmV2F0fXQ== + +"@esbuild/freebsd-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.10.tgz#cd0a1b68bffbcb5b65e65b3fd542e8c7c3edd86b" + integrity sha512-0m0YX1IWSLG9hWh7tZa3kdAugFbZFFx9XrvfpaCMMvrswSTvUZypp0NFKriUurHpBA3xsHVE9Qb/0u2Bbi/otg== + +"@esbuild/linux-arm64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.10.tgz#13b183f432512ed9d9281cc89476caeebe9e9123" + integrity sha512-g1EZJR1/c+MmCgVwpdZdKi4QAJ8DCLP5uTgLWSAVd9wlqk9GMscaNMEViG3aE1wS+cNMzXXgdWiW/VX4J+5nTA== + +"@esbuild/linux-arm@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.10.tgz#dd11e0a5faa3ea94dc80278a601c3be7b4fdf1da" + integrity sha512-whRdrrl0X+9D6o5f0sTZtDM9s86Xt4wk1bf7ltx6iQqrIIOH+sre1yjpcCdrVXntQPCNw/G+XqsD4HuxeS+2QA== + +"@esbuild/linux-ia32@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.10.tgz#4d836f87b92807d9292379963c4888270d282405" + integrity sha512-1vKYCjfv/bEwxngHERp7huYfJ4jJzldfxyfaF7hc3216xiDA62xbXJfRlradiMhGZbdNLj2WA1YwYFzs9IWNPw== + +"@esbuild/linux-loong64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.10.tgz#92eb2ee200c17ef12c7fb3b648231948699e7a4c" + integrity sha512-mvwAr75q3Fgc/qz3K6sya3gBmJIYZCgcJ0s7XshpoqIAIBszzfXsqhpRrRdVFAyV1G9VUjj7VopL2HnAS8aHFA== + +"@esbuild/linux-mips64el@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.10.tgz#14f7d50c40fe7f7ee545a9bd07c6f6e4cba5570e" + integrity sha512-XilKPgM2u1zR1YuvCsFQWl9Fc35BqSqktooumOY2zj7CSn5czJn279j9TE1JEqSqz88izJo7yE4x3LSf7oxHzg== + +"@esbuild/linux-ppc64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.10.tgz#1ab5802e93ae511ce9783e1cb95f37df0f84c4af" + integrity sha512-kM4Rmh9l670SwjlGkIe7pYWezk8uxKHX4Lnn5jBZYBNlWpKMBCVfpAgAJqp5doLobhzF3l64VZVrmGeZ8+uKmQ== + +"@esbuild/linux-riscv64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.10.tgz#4fae25201ef7ad868731d16c8b50b0e386c4774a" + integrity sha512-r1m9ZMNJBtOvYYGQVXKy+WvWd0BPvSxMsVq8Hp4GzdMBQvfZRvRr5TtX/1RdN6Va8JMVQGpxqde3O+e8+khNJQ== + +"@esbuild/linux-s390x@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.10.tgz#126254d8335bb3586918b1ca60beb4abb46e6d54" + integrity sha512-LsY7QvOLPw9WRJ+fU5pNB3qrSfA00u32ND5JVDrn/xG5hIQo3kvTxSlWFRP0NJ0+n6HmhPGG0Q4jtQsb6PFoyg== + +"@esbuild/linux-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.10.tgz#7fa4667b2df81ea0538e1b75e607cf04e526ce91" + integrity sha512-zJUfJLebCYzBdIz/Z9vqwFjIA7iSlLCFvVi7glMgnu2MK7XYigwsonXshy9wP9S7szF+nmwrelNaP3WGanstEg== + +"@esbuild/netbsd-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.10.tgz#2d24727ddc2305619685bf237a46d6087a02ee9a" + integrity sha512-lOMkailn4Ok9Vbp/q7uJfgicpDTbZFlXlnKT2DqC8uBijmm5oGtXAJy2ZZVo5hX7IOVXikV9LpCMj2U8cTguWA== + +"@esbuild/openbsd-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.10.tgz#bf3fc38ee6ecf028c1f0cfe11f61d53cc75fef12" + integrity sha512-/VE0Kx6y7eekqZ+ZLU4AjMlB80ov9tEz4H067Y0STwnGOYL8CsNg4J+cCmBznk1tMpxMoUOf0AbWlb1d2Pkbig== + +"@esbuild/sunos-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.10.tgz#8deabd6dfec6256f80bb101bc59d29dbae99c69b" + integrity sha512-ERNO0838OUm8HfUjjsEs71cLjLMu/xt6bhOlxcJ0/1MG3hNqCmbWaS+w/8nFLa0DDjbwZQuGKVtCUJliLmbVgg== + +"@esbuild/win32-arm64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.10.tgz#1ec1ee04c788c4c57a83370b6abf79587b3e4965" + integrity sha512-fXv+L+Bw2AeK+XJHwDAQ9m3NRlNemG6Z6ijLwJAAVdu4cyoFbBWbEtyZzDeL+rpG2lWI51cXeMt70HA8g2MqIg== + +"@esbuild/win32-ia32@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.10.tgz#a362528d7f3ad5d44fa8710a96764677ef92ebe9" + integrity sha512-3s+HADrOdCdGOi5lnh5DMQEzgbsFsd4w57L/eLKKjMnN0CN4AIEP0DCP3F3N14xnxh3ruNc32A0Na9zYe1Z/AQ== + +"@esbuild/win32-x64@0.17.10": + version "0.17.10" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.10.tgz#ac779220f2da96afd480fb3f3148a292f66e7fc3" + integrity sha512-oP+zFUjYNaMNmjTwlFtWep85hvwUu19cZklB3QsBOcZSs6y7hmH4LNCJ7075bsqzYaNvZFXJlAVaQ2ApITDXtw== "@eslint/eslintrc@^0.4.3": version "0.4.3" @@ -485,10 +486,10 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@eslint/eslintrc@^1.4.1": - version "1.4.1" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== +"@eslint/eslintrc@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz#943309d8697c52fc82c076e90c1c74fbbe69dbff" + integrity sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -500,6 +501,11 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@eslint/js@8.35.0": + version "8.35.0" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz#b7569632b0b788a0ca0e438235154e45d42813a7" + integrity sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw== + "@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -773,7 +779,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -781,18 +787,18 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jsii/check-node@1.75.0": - version "1.75.0" - resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.75.0.tgz#1cfc2ab5b461c1e80d9a4c18a6e351a9a13287ce" - integrity sha512-ODorfPJwN0920DJrZ/R/G3x0UHgtuhz9y10s6Xox1BDobVXOQpfUl3XEQjrTrSE7kiCt2FxZvazT4xu1MU0y6Q== +"@jsii/check-node@1.76.0": + version "1.76.0" + resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.76.0.tgz#3fcb41e916ae8bfba1fca0cbdc406fe0e0b2c7f5" + integrity sha512-iAQohlms0FQNtmAsXOV9Rrd7QDikkLw68R2TPwhlVKuLPdHPKIK3gyeN0jqZzc0luNQ9h+3P7kSqfpKd+Kr79Q== dependencies: chalk "^4.1.2" semver "^7.3.8" -"@jsii/spec@1.75.0", "@jsii/spec@^1.75.0": - version "1.75.0" - resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.75.0.tgz#d15a8fe7764e3d39e727e944452168de35fc2ec3" - integrity sha512-aUF5364qgJRCco1C5HBjkDDBGuHZv0uqD5/IXZ2+3A7P/RXdxJdVup0iMGAWKSAx3yPImgyqgD+JxpAnw06YYg== +"@jsii/spec@1.76.0", "@jsii/spec@^1.76.0": + version "1.76.0" + resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.76.0.tgz#9323aec77f4e0a3ec7c68a5c257b0841f5ad0731" + integrity sha512-7L8KeG44ECq0ulKYWaOr0FQvnFW7RavjxEGvMAdKfIOXb5mZyGERnj5pKl5kmq2m1lWE2VBZELoTfM7dDlAPtg== dependencies: ajv "^8.12.0" @@ -1966,10 +1972,10 @@ dependencies: "@types/glob" "*" -"@types/aws-lambda@^8.10.110": - version "8.10.110" - resolved "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.110.tgz#32a1f9d40b855d69830243492bbb6408098f4c88" - integrity sha512-r6egf2Cwv/JaFTTrF9OXFVUB3j/SXTgM9BwrlbBRjWAa2Tu6GWoDoLflppAZ8uSfbUJdXvC7Br3DjuN9pQ2NUQ== +"@types/aws-lambda@^8.10.111": + version "8.10.111" + resolved "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.111.tgz#9107c405f3011a5c423b5ac93fbf279439558571" + integrity sha512-8HR9UjIKmoemEzE2BviVtFkeenxfbizSu8raFjnT2VXxguZZ2JTlNww7INOH7IA0J/zRa3TjOftkYq6hVNkxDA== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": version "7.20.0" @@ -2037,9 +2043,9 @@ "@types/node" "*" "@types/glob@*": - version "8.0.1" - resolved "https://registry.npmjs.org/@types/glob/-/glob-8.0.1.tgz#6e3041640148b7764adf21ce5c7138ad454725b0" - integrity sha512-8bVUjXZvJacUFkJXHdyZ9iH1Eaj5V7I8c4NdH5sQJsdXkqT4CA5Dhb4yb4VE/3asyx4L9ayZr1NIhTsWHczmMw== + version "8.1.0" + resolved "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz#b63e70155391b0584dce44e7ea25190bbc38f2fc" + integrity sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w== dependencies: "@types/minimatch" "^5.1.2" "@types/node" "*" @@ -2151,9 +2157,9 @@ integrity sha512-uv53RrNdhbkV/3VmVCtfImfYCWC3GTTRn3R11Whni3EJ+gb178tkZBVNj2edLY5CMrB749dQi+SJkg87jsN8UQ== "@types/node@*": - version "18.13.0" - resolved "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" - integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== + version "18.14.2" + resolved "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz#c076ed1d7b6095078ad3cf21dfeea951842778b1" + integrity sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA== "@types/node@18.11.19": version "18.11.19" @@ -2161,9 +2167,9 @@ integrity sha512-YUgMWAQBWLObABqrvx8qKO1enAvBUdjZOAWQ5grBAkp5LQv45jBvYKZ3oFS9iKRCQyFjqw6iuEa1vmFqtxYLZw== "@types/node@^16.9.2": - version "16.18.12" - resolved "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz#e3bfea80e31523fde4292a6118f19ffa24fd6f65" - integrity sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw== + version "16.18.13" + resolved "https://registry.npmjs.org/@types/node/-/node-16.18.13.tgz#c572f8837094c6e3b73918a68674c784f6877fc0" + integrity sha512-l0/3XZ153UTlNOnZK8xSNoJlQda9/WnYgiTdcKKPJSZjdjI9MU+A9oMXOesAWLSnqAaaJhj3qfQsU07Dr8OUwg== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -2322,13 +2328,13 @@ tsutils "^3.21.0" "@typescript-eslint/eslint-plugin@^5": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.52.0.tgz#5fb0d43574c2411f16ea80f5fc335b8eaa7b28a8" - integrity sha512-lHazYdvYVsBokwCdKOppvYJKaJ4S41CgKBcPvyd0xjZNbvQdhn/pnJlGtQksQ/NhInzdaeaSarlBjDXHuclEbg== + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz#2c821ad81b2c786d142279a8292090f77d1881f4" + integrity sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw== dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/type-utils" "5.52.0" - "@typescript-eslint/utils" "5.52.0" + "@typescript-eslint/scope-manager" "5.54.0" + "@typescript-eslint/type-utils" "5.54.0" + "@typescript-eslint/utils" "5.54.0" debug "^4.3.4" grapheme-splitter "^1.0.4" ignore "^5.2.0" @@ -2360,13 +2366,13 @@ debug "^4.3.1" "@typescript-eslint/parser@^5": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.52.0.tgz#73c136df6c0133f1d7870de7131ccf356f5be5a4" - integrity sha512-e2KiLQOZRo4Y0D/b+3y08i3jsekoSkOYStROYmPUnGMEoA0h+k2qOH5H6tcjIc68WDvGwH+PaOrP1XRzLJ6QlA== + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz#def186eb1b1dbd0439df0dacc44fb6d8d5c417fe" + integrity sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ== dependencies: - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/scope-manager" "5.54.0" + "@typescript-eslint/types" "5.54.0" + "@typescript-eslint/typescript-estree" "5.54.0" debug "^4.3.4" "@typescript-eslint/scope-manager@4.33.0": @@ -2377,21 +2383,21 @@ "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" -"@typescript-eslint/scope-manager@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.52.0.tgz#a993d89a0556ea16811db48eabd7c5b72dcb83d1" - integrity sha512-AR7sxxfBKiNV0FWBSARxM8DmNxrwgnYMPwmpkC1Pl1n+eT8/I2NAUPuwDy/FmDcC6F8pBfmOcaxcxRHspgOBMw== +"@typescript-eslint/scope-manager@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz#74b28ac9a3fc8166f04e806c957adb8c1fd00536" + integrity sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg== dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" + "@typescript-eslint/types" "5.54.0" + "@typescript-eslint/visitor-keys" "5.54.0" -"@typescript-eslint/type-utils@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.52.0.tgz#9fd28cd02e6f21f5109e35496df41893f33167aa" - integrity sha512-tEKuUHfDOv852QGlpPtB3lHOoig5pyFQN/cUiZtpw99D93nEBjexRLre5sQZlkMoHry/lZr8qDAt2oAHLKA6Jw== +"@typescript-eslint/type-utils@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz#390717216eb61393a0cad2995da154b613ba7b26" + integrity sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ== dependencies: - "@typescript-eslint/typescript-estree" "5.52.0" - "@typescript-eslint/utils" "5.52.0" + "@typescript-eslint/typescript-estree" "5.54.0" + "@typescript-eslint/utils" "5.54.0" debug "^4.3.4" tsutils "^3.21.0" @@ -2400,10 +2406,10 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/types@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.52.0.tgz#19e9abc6afb5bd37a1a9bea877a1a836c0b3241b" - integrity sha512-oV7XU4CHYfBhk78fS7tkum+/Dpgsfi91IIDy7fjCyq2k6KB63M6gMC0YIvy+iABzmXThCRI6xpCEyVObBdWSDQ== +"@typescript-eslint/types@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz#7d519df01f50739254d89378e0dcac504cab2740" + integrity sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ== "@typescript-eslint/typescript-estree@4.33.0", "@typescript-eslint/typescript-estree@^4.33.0": version "4.33.0" @@ -2418,29 +2424,29 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.52.0.tgz#6408cb3c2ccc01c03c278cb201cf07e73347dfca" - integrity sha512-WeWnjanyEwt6+fVrSR0MYgEpUAuROxuAH516WPjUblIrClzYJj0kBbjdnbQXLpgAN8qbEuGywiQsXUVDiAoEuQ== +"@typescript-eslint/typescript-estree@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz#f6f3440cabee8a43a0b25fa498213ebb61fdfe99" + integrity sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ== dependencies: - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/visitor-keys" "5.52.0" + "@typescript-eslint/types" "5.54.0" + "@typescript-eslint/visitor-keys" "5.54.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.52.0.tgz#b260bb5a8f6b00a0ed51db66bdba4ed5e4845a72" - integrity sha512-As3lChhrbwWQLNk2HC8Ree96hldKIqk98EYvypd3It8Q1f8d5zWyIoaZEp2va5667M4ZyE7X8UUR+azXrFl+NA== +"@typescript-eslint/utils@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz#3db758aae078be7b54b8ea8ea4537ff6cd3fbc21" + integrity sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw== dependencies: "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.52.0" - "@typescript-eslint/types" "5.52.0" - "@typescript-eslint/typescript-estree" "5.52.0" + "@typescript-eslint/scope-manager" "5.54.0" + "@typescript-eslint/types" "5.54.0" + "@typescript-eslint/typescript-estree" "5.54.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" semver "^7.3.7" @@ -2453,12 +2459,12 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@5.52.0": - version "5.52.0" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.52.0.tgz#e38c971259f44f80cfe49d97dbffa38e3e75030f" - integrity sha512-qMwpw6SU5VHCPr99y274xhbm+PRViK/NATY6qzt+Et7+mThGuFSl/ompj2/hrBlRP/kq+BFdgagnOSgw9TB0eA== +"@typescript-eslint/visitor-keys@5.54.0": + version "5.54.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz#846878afbf0cd67c19cfa8d75947383d4490db8f" + integrity sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA== dependencies: - "@typescript-eslint/types" "5.52.0" + "@typescript-eslint/types" "5.54.0" eslint-visitor-keys "^3.3.0" "@xmldom/xmldom@^0.8.6": @@ -2881,10 +2887,10 @@ aws-sdk-mock@5.6.0: sinon "^11.1.1" traverse "^0.6.6" -aws-sdk@^2.1317.0, aws-sdk@^2.928.0: - version "2.1317.0" - resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1317.0.tgz#b1534696b840654a55660eed467ed7ddbbb2e1d1" - integrity sha512-9gQ3ApcG4OhM19LEcmd/1jclwHvI3jjVaFYNQkY88g2eFJDW5T8qP+u2epdv+o3bPWxzg0TcyPhOSlN4xAnIJQ== +aws-sdk@^2.1325.0, aws-sdk@^2.928.0: + version "2.1325.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1325.0.tgz#4529ede089ee8db79d6eb04ab46a211bfddbbe5b" + integrity sha512-ztg9HG5aoUHTprY+/eqjqb25E4joCgz+8ToxsP4OSKFQCtaBcF6my03j4e/J2j3fmpPifJnZSPMu4kV7DBj8WA== dependencies: buffer "4.9.2" events "1.1.1" @@ -3252,9 +3258,9 @@ camelcase@^6.2.0, camelcase@^6.3.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001449: - version "1.0.30001453" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001453.tgz#6d3a1501622bf424a3cee5ad9550e640b0de3de8" - integrity sha512-R9o/uySW38VViaTrOtwfbFEiBFUh7ST3uIG4OEymIG3/uKdHDO4xk/FaqfUw0d+irSUyFPy3dZszf9VvSTPnsA== + version "1.0.30001458" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz#871e35866b4654a7d25eccca86864f411825540c" + integrity sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w== case@1.6.3, case@^1.6.3: version "1.6.3" @@ -3266,29 +3272,29 @@ caseless@~0.12.0: resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -cdk-generate-synthetic-examples@^0.1.155: - version "0.1.155" - resolved "https://registry.npmjs.org/cdk-generate-synthetic-examples/-/cdk-generate-synthetic-examples-0.1.155.tgz#a2f72783d8255eff983a2501c5249e6bf068c5e0" - integrity sha512-Ml9Pga/f8IYbRcKXeeqyMP4uc9yYcbQ/jBzpwYb4a074TXMsrjKvpqiU7r4O0x74yxAZntPpjteDFxy6GoSncg== +cdk-generate-synthetic-examples@^0.1.167: + version "0.1.167" + resolved "https://registry.npmjs.org/cdk-generate-synthetic-examples/-/cdk-generate-synthetic-examples-0.1.167.tgz#1fba547e4cab09b914c0cf36e72d618cedbf8df3" + integrity sha512-rjSRrw1fzalETc1tI5pm8aytdnuaqa6/oDD/r2fsSPzWzoOtV8W+TCNx4/BkPgZxaKJwwURpUAx7Jl8R12eZWg== dependencies: - "@jsii/spec" "^1.75.0" + "@jsii/spec" "^1.76.0" fs-extra "^10.1.0" - jsii "^1.75.0" - jsii-reflect "^1.75.0" - jsii-rosetta "^1.75.0" - yargs "^17.6.2" + jsii "^1.76.0" + jsii-reflect "^1.76.0" + jsii-rosetta "^1.76.0" + yargs "^17.7.1" -cdk8s-plus-24@2.4.23: - version "2.4.23" - resolved "https://registry.npmjs.org/cdk8s-plus-24/-/cdk8s-plus-24-2.4.23.tgz#dd3f49a6d4c2dac637a820b567b80e17e829799c" - integrity sha512-hPNSo6UQUa/wSo44IRqcoMVVzhEgweuRFSvE5TNMaYlDjwsXG+4u8XYV+5qIocZPli+epYqejgev2zleafTh9g== +cdk8s-plus-24@2.4.40: + version "2.4.40" + resolved "https://registry.npmjs.org/cdk8s-plus-24/-/cdk8s-plus-24-2.4.40.tgz#f27c4c5f0adf20ec58294ac7452fdbe3bcb64a9a" + integrity sha512-vDs1Q1XJ1cVg9ap/onOPEC4QRhuCMIHod7TeeQqO8v6I1bB2W9sZc52aLBEc4u9yEuI7/pP2t1rL9m+obcITvw== dependencies: minimatch "^3.1.2" -cdk8s@^2.7.2: - version "2.7.2" - resolved "https://registry.npmjs.org/cdk8s/-/cdk8s-2.7.2.tgz#64ead388fcba5ff08ff920fa52d65e8dfac3ad95" - integrity sha512-ID5oKvKGSh5OjSCC6tzoZDgyepcPgzVshqdgEO+1gwaO+ep/UNBaDYmFbCTU8EPwjdEdOwq2VFTkmoJTu9/r7g== +cdk8s@^2.7.15: + version "2.7.15" + resolved "https://registry.npmjs.org/cdk8s/-/cdk8s-2.7.15.tgz#f7d40a17e5ce662208d2713e02a1902593d1caa0" + integrity sha512-bQIYHUas23SnjSso1ajZdzs0uKY76jisv41KhdL0RMaG+kvHZ5U6WqbKgwMfocPB9DDKxl+k00emn/g5Eh+Nvg== dependencies: fast-json-patch "^3.1.1" follow-redirects "^1.15.2" @@ -3520,10 +3526,10 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -codemaker@1.75.0, codemaker@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.75.0.tgz#a54953cf590cb43629c364f62aaf53a7693fc031" - integrity sha512-HGZQMJb+IXlGD5MJj6Ae2IXzkd4aoIufj/OfM0HxpJnldWx5rlzBjzgpI+YcK1RdaLm3HWMNDtTLti0qMsHtSA== +codemaker@1.76.0, codemaker@^1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.76.0.tgz#28a2c517ee53bdcfb02030c82520f669db6e5286" + integrity sha512-EqnBOOiEV+kjyRghA5Z0TX22VnVH2Mgo2diOSYelcmntlTSiQkZimGof6jxE5j1buzjEVBK1d1W7bhRKYGegUg== dependencies: camelcase "^6.3.0" decamelize "^5.0.1" @@ -3693,9 +3699,9 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control- integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== constructs@^10.0.0: - version "10.1.252" - resolved "https://registry.npmjs.org/constructs/-/constructs-10.1.252.tgz#a241329ffc50451b6de4fb9147ef32b0e181a515" - integrity sha512-8j3bcoSTlIjbCu1tflWHvipVDWmllUNu3dEWb5GXvsXCiYuH0NtXCCN5q6GmFInDcspZp8WOYu66uqQ8Bk7jzQ== + version "10.1.264" + resolved "https://registry.npmjs.org/constructs/-/constructs-10.1.264.tgz#84d418b582e6938b998d67e493a6db49011277bc" + integrity sha512-f9db+zgEV9xiIhmHxBuxNU2DjmnIQkM5M4IyLvjP+pBtS3r+PflQFwdZlDuy3K84NMnSaI4J/Sz5i5aNgwmDAg== conventional-changelog-angular@^5.0.12: version "5.0.13" @@ -4408,9 +4414,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.4.284: - version "1.4.300" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.300.tgz#37097e9bcdef687fb98abb5184434bdb958dfcd9" - integrity sha512-tHLIBkKaxvG6NnDWuLgeYrz+LTwAnApHm2R3KBNcRrFn0qLmTrqQeB4X4atfN6YJbkOOOSdRBeQ89OfFUelnEQ== + version "1.4.314" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.314.tgz#33e4ad7a2ca2ddbe2e113874cc0c0e2a00cb46bf" + integrity sha512-+3RmNVx9hZLlc0gW//4yep0K5SYKmIvB5DXg1Yg6varsuAHlHwTeqeygfS8DWwLCsNOWrgj+p9qgM5WYjw1lXQ== emittery@^0.8.1: version "0.8.1" @@ -4593,33 +4599,33 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -esbuild@^0.17.8: - version "0.17.8" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz#f7f799abc7cdce3f0f2e3e0c01f120d4d55193b4" - integrity sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g== +esbuild@^0.17.10: + version "0.17.10" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.17.10.tgz#3be050561b34c5dc05b46978f4e1f326d5cc9437" + integrity sha512-n7V3v29IuZy5qgxx25TKJrEm0FHghAlS6QweUcyIgh/U0zYmQcvogWROitrTyZId1mHSkuhhuyEXtI9OXioq7A== optionalDependencies: - "@esbuild/android-arm" "0.17.8" - "@esbuild/android-arm64" "0.17.8" - "@esbuild/android-x64" "0.17.8" - "@esbuild/darwin-arm64" "0.17.8" - "@esbuild/darwin-x64" "0.17.8" - "@esbuild/freebsd-arm64" "0.17.8" - "@esbuild/freebsd-x64" "0.17.8" - "@esbuild/linux-arm" "0.17.8" - "@esbuild/linux-arm64" "0.17.8" - "@esbuild/linux-ia32" "0.17.8" - "@esbuild/linux-loong64" "0.17.8" - "@esbuild/linux-mips64el" "0.17.8" - "@esbuild/linux-ppc64" "0.17.8" - "@esbuild/linux-riscv64" "0.17.8" - "@esbuild/linux-s390x" "0.17.8" - "@esbuild/linux-x64" "0.17.8" - "@esbuild/netbsd-x64" "0.17.8" - "@esbuild/openbsd-x64" "0.17.8" - "@esbuild/sunos-x64" "0.17.8" - "@esbuild/win32-arm64" "0.17.8" - "@esbuild/win32-ia32" "0.17.8" - "@esbuild/win32-x64" "0.17.8" + "@esbuild/android-arm" "0.17.10" + "@esbuild/android-arm64" "0.17.10" + "@esbuild/android-x64" "0.17.10" + "@esbuild/darwin-arm64" "0.17.10" + "@esbuild/darwin-x64" "0.17.10" + "@esbuild/freebsd-arm64" "0.17.10" + "@esbuild/freebsd-x64" "0.17.10" + "@esbuild/linux-arm" "0.17.10" + "@esbuild/linux-arm64" "0.17.10" + "@esbuild/linux-ia32" "0.17.10" + "@esbuild/linux-loong64" "0.17.10" + "@esbuild/linux-mips64el" "0.17.10" + "@esbuild/linux-ppc64" "0.17.10" + "@esbuild/linux-riscv64" "0.17.10" + "@esbuild/linux-s390x" "0.17.10" + "@esbuild/linux-x64" "0.17.10" + "@esbuild/netbsd-x64" "0.17.10" + "@esbuild/openbsd-x64" "0.17.10" + "@esbuild/sunos-x64" "0.17.10" + "@esbuild/win32-arm64" "0.17.10" + "@esbuild/win32-ia32" "0.17.10" + "@esbuild/win32-x64" "0.17.10" escalade@^3.1.1: version "3.1.1" @@ -4852,11 +4858,12 @@ eslint@^7.32.0: v8-compile-cache "^2.0.3" eslint@^8: - version "8.34.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz#fe0ab0ef478104c1f9ebc5537e303d25a8fb22d6" - integrity sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg== + version "8.35.0" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz#fffad7c7e326bae606f0e8f436a6158566d42323" + integrity sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw== dependencies: - "@eslint/eslintrc" "^1.4.1" + "@eslint/eslintrc" "^2.0.0" + "@eslint/js" "8.35.0" "@humanwhocodes/config-array" "^0.11.8" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -4870,7 +4877,7 @@ eslint@^8: eslint-utils "^3.0.0" eslint-visitor-keys "^3.3.0" espree "^9.4.0" - esquery "^1.4.0" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" @@ -4919,7 +4926,7 @@ esprima@^4.0.0, esprima@^4.0.1: resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: +esquery@^1.4.0, esquery@^1.4.2: version "1.4.2" resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz#c6d3fee05dd665808e2ad870631f221f5617b1d1" integrity sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng== @@ -7009,73 +7016,90 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.75.0.tgz#d4b02e8ed16aa07e0ac618fa90792ff99d5e73f0" - integrity sha512-4MRc2ikiTHs3kKMFjcvwSeLjDMTRVQ5+ImgU8+NvfdmMANkP7DG6tbKotZy6Jz2/Afnu2PtSKXlnLBKHNMFmfg== +jsii-diff@1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.76.0.tgz#8aba54481e1ac7dcd7e2c592d1ef11defe244b2a" + integrity sha512-i3U753ae5WzaiGLJV8ZFTu9rlGQGVuSJADCHxteP2UuHuFSWRSPY2iMhtyg7tEoQmdNYjPznM7fesqrDHLxBOg== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "^1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" fs-extra "^10.1.0" - jsii-reflect "^1.75.0" + jsii-reflect "^1.76.0" log4js "^6.7.1" yargs "^16.2.0" -jsii-pacmak@1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.75.0.tgz#2ecba3c95d587003c763ee8fc7516d30997cbabf" - integrity sha512-ENH5nNwMjN4CIK9D5mJ8OHDjiwInzQItQQmGwCdPJFLlUN9+9EkhYy2gEPVYPwh7e294c2nJ55DmiOj2CWR17g== +jsii-pacmak@1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.76.0.tgz#e0d95bc20f757f7b067dc545587bc38795611b09" + integrity sha512-70h0puIRpDeDyYk/jLxQk7vPbg3w3ppJRATlF0qPntMk/WnSo4uvr8hlz1BmRzOOvQ7JqXBuNOaVd+bp7Xolbw== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "^1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" clone "^2.1.2" - codemaker "^1.75.0" + codemaker "^1.76.0" commonmark "^0.30.0" escape-string-regexp "^4.0.0" fs-extra "^10.1.0" - jsii-reflect "^1.75.0" - jsii-rosetta "^1.75.0" + jsii-reflect "^1.76.0" + jsii-rosetta "^1.76.0" semver "^7.3.8" spdx-license-list "^6.6.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@1.75.0, jsii-reflect@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.75.0.tgz#136564eb8ec9a94a9fe218e3d275e80196cd6285" - integrity sha512-oB8X2MpLZbpl8T7XfD+jSADLjzhEMnCZH8BSY3hxSH8TGdhMUZriFHFgmz1NshkZXDh0zRz+xF2a8+uqEIKRYw== +jsii-reflect@1.76.0, jsii-reflect@^1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.76.0.tgz#a80ab48f9bea9f1ad4212e8b2057eb0ae325e1e0" + integrity sha512-voS5WyeitP3o0knus00v00NlxVLbaU9ykvEDamFw5KPEc4z4wvAwDG9wBfNmdO1OulXgID41WhMzJOEJFKle6A== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "^1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" chalk "^4" fs-extra "^10.1.0" - oo-ascii-tree "^1.75.0" + oo-ascii-tree "^1.76.0" yargs "^16.2.0" -jsii-rosetta@1.75.0, jsii-rosetta@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.75.0.tgz#85a96669fc60f69d29409608a694ed063abcadd9" - integrity sha512-zsV8F0BoXTvS46N1/QCwapMXamQhJKFaAIapFBWk0a4l84v+FSYOWnKbgZz+FVZEuu3VBJpxg6uKE9R9A8Hvag== +jsii-rosetta@^1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.76.0.tgz#450256361bdbb0d6d5524c4817a7b345d9647a57" + integrity sha512-y3OcYebjMdK/4Yxt8P9tMalK9Szmq8Xc4VXD3kGDIEulMjUxo3TpEUZc9WEfzVu6A+lSl/WRAwV50ZgzQyVWZg== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "1.76.0" "@xmldom/xmldom" "^0.8.6" commonmark "^0.30.0" fast-glob "^3.2.12" - jsii "1.75.0" + jsii "1.76.0" semver "^7.3.8" semver-intersect "^1.4.0" typescript "~3.9.10" workerpool "^6.3.1" yargs "^16.2.0" -jsii@1.75.0, jsii@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/jsii/-/jsii-1.75.0.tgz#e18fc8cb3ad985da93fb1513fc1e4d8ca191ff98" - integrity sha512-9CWt2IQcM6v5k4XZnaSnsK9epfIJfHWMyB69uOjITZpwYjF0CDzLrh/a8l1RyC3COSpp1K1yTjaebHEivyVr4Q== +jsii-rosetta@v4.9-next: + version "4.9.0-dev.2" + resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-4.9.0-dev.2.tgz#2f08066badc532b7716f44c4af99584d4d904472" + integrity sha512-4SjSIJcujNmettnwXgsQN6BA9hZRdWqkqTPtJfg9C5Jz2dUa2fOZL4+GglAaR/z4hVUL4nNi0rY4IhOQ3l1s0A== + dependencies: + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" + "@xmldom/xmldom" "^0.8.6" + commonmark "^0.30.0" + fast-glob "^3.2.12" + jsii v4.9-next + semver "^7.3.8" + semver-intersect "^1.4.0" + typescript "~4.9.5" + workerpool "^6.4.0" + yargs "^17.7.1" + +jsii@1.76.0, jsii@^1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/jsii/-/jsii-1.76.0.tgz#b40c98108b1cac2cb86a5eb2b3f201ba52a316b6" + integrity sha512-IlQmxPPnscn2Va/cnnXRnQ7bnxEkO8ImKW0MBlEr66oqxhFQ9jy9+FWzOp/5kfHzhyyyM5mcqitB8O6fr1moIw== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "^1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" case "^1.6.3" chalk "^4" fast-deep-equal "^3.1.3" @@ -7089,12 +7113,12 @@ jsii@1.75.0, jsii@^1.75.0: yargs "^16.2.0" jsii@v4.9-next: - version "4.9.0-dev.0" - resolved "https://registry.npmjs.org/jsii/-/jsii-4.9.0-dev.0.tgz#da1d4ce42879e718148e956a5a3ceeb0113377ac" - integrity sha512-otGy/z3jvUmn6GLQudPcpu5f8DhCZiA0RdS/tBbdEQCjdnWv/zrS6ZPbeeBaozuSdsJ/ni9jmQsWZIh6nz7vXA== + version "4.9.0-dev.1" + resolved "https://registry.npmjs.org/jsii/-/jsii-4.9.0-dev.1.tgz#3fcc0001a425f7cf933260b9b9dd999ca71739b6" + integrity sha512-1neCv7G/y9Ihku5ZEz2cDMuSNXpZYxNuTS1ycVXZ0ZhOVGn0+s0ghkOLj+Xecei3M0fBfZxlLiHSpw3xrJT/Mg== dependencies: - "@jsii/check-node" "1.75.0" - "@jsii/spec" "^1.75.0" + "@jsii/check-node" "1.76.0" + "@jsii/spec" "^1.76.0" case "^1.6.3" chalk "^4" downlevel-dts "^0.11.0" @@ -7173,7 +7197,7 @@ json5@2.x, json5@^2.2.2: resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -json5@^1.0.1: +json5@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== @@ -7673,18 +7697,7 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -log4js@^6.7.1: - version "6.7.1" - resolved "https://registry.npmjs.org/log4js/-/log4js-6.7.1.tgz#06e12b1ac915dd1067146ffad8215f666f7d2c51" - integrity sha512-lzbd0Eq1HRdWM2abSD7mk6YIVY0AogGJzb/z+lqzRk+8+XJP+M6L1MS5FUSc3jjGru4dbKjEMJmqlsoYYpuivQ== - dependencies: - date-format "^4.0.14" - debug "^4.3.4" - flatted "^3.2.7" - rfdc "^1.3.0" - streamroller "^3.1.3" - -log4js@^6.8.0: +log4js@^6.7.1, log4js@^6.8.0: version "6.8.0" resolved "https://registry.npmjs.org/log4js/-/log4js-6.8.0.tgz#f0fe9b2b82725aaf97f20692e23381a5c5722448" integrity sha512-g+V8gZyurIexrOvWQ+AcZsIvuK/lBnx2argejZxL4gVZ4Hq02kUYH6WZOnqxgBml+zzQZYdaEoTN84B6Hzm8Fg== @@ -7720,9 +7733,9 @@ lru-cache@^6.0.0: yallist "^4.0.0" lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: - version "7.15.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.15.0.tgz#4437550407da5ec8c4fe0946a137fe2f7f07a171" - integrity sha512-LKpNuyKR1lRsqN5DatvMOkW2nmUAwI22HoQK604nhs+WiRWSIC0MFUKq2XYUKv1fCVPK9Cro4d4Il3DxM80/fQ== + version "7.18.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.1.tgz#4716408dec51d5d0104732647f584d1f6738b109" + integrity sha512-8/HcIENyQnfUTCDizRu9rrDyG6XG/21M4X7/YEGZeD76ZJilFPAUVb/2zysFf7VVO1LEjCDFyHp8pMMvozIrvg== lru-queue@^0.1.0: version "0.1.0" @@ -8003,9 +8016,9 @@ min-indent@^1.0.0: integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== minimatch@>=3.1: - version "6.2.0" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz#2b70fd13294178c69c04dfc05aebdb97a4e79e42" - integrity sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg== + version "7.4.1" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-7.4.1.tgz#166705f9417985ba5149f2dbf2fa50c29832913b" + integrity sha512-Oz1iPEP+MGl7KS3SciLsLLcuZ7VsBfb7Qrz/jYt/s/sYAv272P26HSLz2f77Y6hzTKXiBi6g765fqpEDNc5fJw== dependencies: brace-expansion "^2.0.1" @@ -8111,9 +8124,9 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3. yallist "^4.0.0" minipass@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz#00bfbaf1e16e35e804f4aa31a7c1f6b8d9f0ee72" - integrity sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw== + version "4.2.4" + resolved "https://registry.npmjs.org/minipass/-/minipass-4.2.4.tgz#7d0d97434b6a19f59c5c3221698b48bbf3b2cd06" + integrity sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ== minizlib@^1.3.3: version "1.3.3" @@ -8847,10 +8860,10 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.75.0: - version "1.75.0" - resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.75.0.tgz#966b2b373b6583fb5246e19b9ead534ca9afc72f" - integrity sha512-rM9YrFT0Zzes3nLF37sGJIlHIjLQpnEI17LcbioXw83oMHqdc8QW5pE9/IHkYlYRbN2Z+sRouSCkrXFZRai2Mg== +oo-ascii-tree@^1.76.0: + version "1.76.0" + resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.76.0.tgz#776630f3e3df43a3a5082cbf23fa40e3ada808ab" + integrity sha512-I/me4GK6Dybc9lsPYZJdnd1OOFbbnZtfEIIizrbTuFx/v1if375Y59w9ol/TJ75MlSAKs4aHj7Xm+A4E0JitSw== open@^7.4.2: version "7.4.2" @@ -9445,10 +9458,10 @@ progress@^2.0.0, progress@^2.0.3: resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -projen@^0.67.57: - version "0.67.57" - resolved "https://registry.npmjs.org/projen/-/projen-0.67.57.tgz#9c5c546d18c961339fb00a49a556b22822686e39" - integrity sha512-0FGTllWD6tf9ZDgcjBnnbBJmUjtwMOOiZAu6oI4GwIqoySt7uyCTv6uG71OjyQPhsM6iXiLeBJVz57PSJu4g/g== +projen@^0.67.69: + version "0.67.69" + resolved "https://registry.npmjs.org/projen/-/projen-0.67.69.tgz#ec666e340395a3b429581a91733b6856d0602e86" + integrity sha512-F28eW4CZFQwsb93omeVfzAoK9hEajqrzBzKZCwIfKaEupAjqJ8KJkc29FW4MnI7tbZ0DzHg75u0yzzNtotaEXg== dependencies: "@iarna/toml" "^2.2.5" case "^1.6.3" @@ -9652,9 +9665,9 @@ quote-unquote@^1.0.0: integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg== raw-body@^2.2.0: - version "2.5.1" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + version "2.5.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -9821,18 +9834,18 @@ readable-stream@1.1.x: string_decoder "~0.10.x" readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.1" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz#f9f9b5f536920253b3d26e7660e7da4ccff9bb62" + integrity sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -10565,7 +10578,7 @@ statuses@2.0.1: resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -streamroller@^3.1.3, streamroller@^3.1.5: +streamroller@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== @@ -11040,12 +11053,12 @@ ts-node@^9.1.1: yn "3.1.1" tsconfig-paths@^3.10.1, tsconfig-paths@^3.14.1: - version "3.14.1" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" - integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + version "3.14.2" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== dependencies: "@types/json5" "^0.0.29" - json5 "^1.0.1" + json5 "^1.0.2" minimist "^1.2.6" strip-bom "^3.0.0" @@ -11188,9 +11201,9 @@ typescript@^4.5.5, typescript@~4.9.5: integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typescript@next: - version "5.0.0-dev.20230222" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.0.0-dev.20230222.tgz#58809d36b989d244ef037ae5f869f0fc233a952c" - integrity sha512-OCNanAIcGf3Uy1aBvLbPNe524MnDEZChefbzgo9gvEZPYNG7Zma1C6dXuOBSCapLgbLHksOTyoPwixKTbDkZPQ== + version "5.1.0-dev.20230301" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.1.0-dev.20230301.tgz#3250b647dfd19942326bf904211350cdbbfdfe79" + integrity sha512-aJ0PIgQ00zlf9npD2tri7MWDAooMoh3iIn4v0hAMSRCSKqJjTzt7fVopvdtbvWPKripipxeXnX5mhkBZcGrEKQ== typescript@~3.8.3: version "3.8.3" @@ -11614,10 +11627,10 @@ wordwrap@>=0.0.2, wordwrap@^1.0.0: resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -workerpool@^6.3.1: - version "6.3.1" - resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.3.1.tgz#80a9b76e70556acfb1457a3984f8637717f7cdee" - integrity sha512-0x7gJm1rhpn5SPG9NENOxPtbfUZZtK/qOg6gEdSqeDBA3dTeR91RJqSPjccPRCkhNfrnnl/dWxSSj5w9CtdzNA== +workerpool@^6.3.1, workerpool@^6.4.0: + version "6.4.0" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.4.0.tgz#f8d5cfb45fde32fa3b7af72ad617c3369567a462" + integrity sha512-i3KR1mQMNwY2wx20ozq2EjISGtQWDIfV56We+yGJ5yDs8jTwQiLLaqHlkBHITlCuJnYlVRmXegxFxZg7gqI++A== wrap-ansi@^6.2.0: version "6.2.0" @@ -11866,20 +11879,7 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.1.1, yargs@^17.6.2, yargs@^17.7.0: - version "17.7.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.0.tgz#b21e9af1e0a619a2a9c67b1133219b2975a07985" - integrity sha512-dwqOPg5trmrre9+v8SUo2q/hAwyKoVfu8OC1xPHKJGNdxAvPl4sKxL4vBnh3bQz/ZvvGAFeA5H3ou2kcOY8sQQ== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yargs@^17.7.1: +yargs@^17.1.1, yargs@^17.7.1: version "17.7.1" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==