diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92c67747d9692..a16033a986b29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ $ yarn install ``` We recommend that you use [Visual Studio Code](https://code.visualstudio.com/) to work on the CDK. -We use `eslint` to keep our code consistent in terms of style and reducing defects. We recommend installing the +We use `eslint` to keep our code consistent in terms of style and reducing defects. We recommend installing the [eslint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) as well. ### Repo Layout @@ -726,7 +726,7 @@ these directories. ### Linking against this repository If you are developing your own CDK application or library and want to use the locally checked out version of the -AWS CDK, instead of the the version of npm, the `./link-all.sh` script will help here. +AWS CDK, instead of the version of npm, the `./link-all.sh` script will help here. This script symlinks the built modules from the local AWS CDK repo under the `node_modules/` folder of the CDK app or library. diff --git a/allowed-breaking-changes.txt b/allowed-breaking-changes.txt index 56b1145d61b39..599cc80596857 100644 --- a/allowed-breaking-changes.txt +++ b/allowed-breaking-changes.txt @@ -115,4 +115,9 @@ removed:@aws-cdk/aws-lambda-event-sources.SelfManagedKafkaEventSourceProps.retry removed:@aws-cdk/aws-lambda-event-sources.SelfManagedKafkaEventSourceProps.tumblingWindow base-types:@aws-cdk/aws-lambda-event-sources.KafkaEventSourceProps base-types:@aws-cdk/aws-lambda-event-sources.ManagedKafkaEventSourceProps -base-types:@aws-cdk/aws-lambda-event-sources.SelfManagedKafkaEventSourceProps \ No newline at end of file +base-types:@aws-cdk/aws-lambda-event-sources.SelfManagedKafkaEventSourceProps + +# fixed vpc property of BaseLoadBalancer so it correctly implements I(Application|Network)LoadBalancer (i.e: must be optional) +changed-type:@aws-cdk/aws-elasticloadbalancingv2.ApplicationLoadBalancer.vpc +changed-type:@aws-cdk/aws-elasticloadbalancingv2.BaseLoadBalancer.vpc +changed-type:@aws-cdk/aws-elasticloadbalancingv2.NetworkLoadBalancer.vpc diff --git a/buildspec.yaml b/buildspec.yaml index edae3c9c42fa1..db462c8b987be 100644 --- a/buildspec.yaml +++ b/buildspec.yaml @@ -28,7 +28,7 @@ phases: post_build: commands: # Short-circuit: Don't run pack if the above build failed. - - '[[ "$CODEBUILD_BUILD_SUCCEEDING" -eq 1 ]] || exit 1' + - '[ ${CODEBUILD_BUILD_SUCCEEDING:-0} -eq 1 ] || exit 1' - "[ -f .BUILD_COMPLETED ] && /bin/bash ./pack.sh" - /bin/bash ./scripts/cache-store.sh artifacts: diff --git a/package.json b/package.json index a1bfab7445556..be3d9e61e48c4 100644 --- a/package.json +++ b/package.json @@ -16,15 +16,15 @@ }, "devDependencies": { "@yarnpkg/lockfile": "^1.1.0", - "cdk-generate-synthetic-examples": "^0.1.1", + "cdk-generate-synthetic-examples": "^0.1.2", "conventional-changelog-cli": "^2.2.2", "fs-extra": "^9.1.0", "graceful-fs": "^4.2.9", "jest-junit": "^13.0.0", - "jsii-diff": "^1.50.0", - "jsii-pacmak": "^1.50.0", - "jsii-reflect": "^1.50.0", - "jsii-rosetta": "^1.50.0", + "jsii-diff": "^1.52.1", + "jsii-pacmak": "^1.52.1", + "jsii-reflect": "^1.52.1", + "jsii-rosetta": "^1.52.1", "lerna": "^4.0.0", "patch-package": "^6.4.7", "standard-version": "^9.3.2", diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/README.md b/packages/@aws-cdk-containers/ecs-service-extensions/README.md index 115c8785ddbc1..84dd42fc93eff 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/README.md +++ b/packages/@aws-cdk-containers/ecs-service-extensions/README.md @@ -109,7 +109,43 @@ nameDescription.add(new Container({ Every `ServiceDescription` requires at minimum that you add a `Container` extension which defines the main application (essential) container to run for the service. -After that, you can optionally enable additional features for the service using the `ServiceDescription.add()` method: +### Logging using `awslogs` log driver + +If no observability extensions have been configured for a service, the ECS Service Extensions configures an `awslogs` log driver for the application container of the service to send the container logs to CloudWatch Logs. + +You can either provide a log group to the `Container` extension or one will be created for you by the CDK. + +Following is an example of an application with an `awslogs` log driver configured for the application container: + +```ts +const environment = new Environment(stack, 'production'); + +const nameDescription = new ServiceDescription(); +nameDescription.add(new Container({ + cpu: 1024, + memoryMiB: 2048, + trafficPort: 80, + image: ContainerImage.fromRegistry('nathanpeck/name'), + environment: { + PORT: '80', + }, + logGroup: new awslogs.LogGroup(stack, 'MyLogGroup'), +})); +``` + +If a log group is not provided, no observability extensions have been created, and the `ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER` feature flag is enabled, then logging will be configured by default and a log group will be created for you. + +The `ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER` feature flag is enabled by default in any CDK apps that are created with CDK v1.140.0 or v2.8.0 and later. + +To enable default logging for previous versions, ensure that the `ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER` flag within the application stack context is set to true, like so: + +```ts +stack.node.setContext(cxapi.ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER, true); +``` + +Alternatively, you can also set the feature flag in the `cdk.json` file. For more information, refer the [docs](https://docs.aws.amazon.com/cdk/v2/guide/featureflags.html). + +After adding the `Container` extension, you can optionally enable additional features for the service using the `ServiceDescription.add()` method: ```ts nameDescription.add(new AppMeshExtension({ mesh })); diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/container.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/container.ts index 10c61401e90d3..2711108e4f0ff 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/container.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/container.ts @@ -1,4 +1,7 @@ import * as ecs from '@aws-cdk/aws-ecs'; +import * as awslogs from '@aws-cdk/aws-logs'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; import { Service } from '../service'; import { ServiceExtension } from './extension-interfaces'; @@ -38,6 +41,13 @@ export interface ContainerExtensionProps { readonly environment?: { [key: string]: string, } + + /** + * The log group into which application container logs should be routed. + * + * @default - A log group is automatically created for you if the `ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER` feature flag is set. + */ + readonly logGroup?: awslogs.ILogGroup; } /** @@ -51,6 +61,11 @@ export class Container extends ServiceExtension { */ public readonly trafficPort: number; + /** + * The log group into which application container logs should be routed. + */ + public logGroup?: awslogs.ILogGroup; + /** * The settings for the container. */ @@ -60,11 +75,12 @@ export class Container extends ServiceExtension { super('service-container'); this.props = props; this.trafficPort = props.trafficPort; + this.logGroup = props.logGroup; } - // @ts-ignore - Ignore unused params that are required for abstract class extend public prehook(service: Service, scope: Construct) { this.parentService = service; + this.scope = scope; } // This hook sets the overall task resource requirements to the @@ -93,6 +109,31 @@ export class Container extends ServiceExtension { containerProps = hookProvider.mutateContainerDefinition(containerProps); }); + // If no observability extensions have been added to the service description then we can configure the `awslogs` log driver + if (!containerProps.logging) { + // Create a log group for the service if one is not provided by the user (only if feature flag is set) + if (!this.logGroup && this.parentService.node.tryGetContext(cxapi.ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER)) { + this.logGroup = new awslogs.LogGroup(this.scope, `${this.parentService.id}-logs`, { + logGroupName: `${this.parentService.id}-logs`, + removalPolicy: cdk.RemovalPolicy.DESTROY, + retention: awslogs.RetentionDays.ONE_MONTH, + }); + } + + if (this.logGroup) { + containerProps = { + ...containerProps, + logging: new ecs.AwsLogDriver({ + streamPrefix: this.parentService.id, + logGroup: this.logGroup, + }), + }; + } + } else { + if (this.logGroup) { + throw Error(`Log configuration already specified. You cannot provide a log group for the application container of service '${this.parentService.id}' while also adding log configuration separately using service extensions.`); + } + } this.container = taskDefinition.addContainer('app', containerProps); // Create a port mapping for the container diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/scale-on-cpu-utilization.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/scale-on-cpu-utilization.ts index ec6ce9662535f..2aa60ebc96364 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/scale-on-cpu-utilization.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/extensions/scale-on-cpu-utilization.ts @@ -2,8 +2,13 @@ import * as ecs from '@aws-cdk/aws-ecs'; import * as cdk from '@aws-cdk/core'; import { ServiceExtension, ServiceBuild } from './extension-interfaces'; + /** * The autoscaling settings. + * + * @deprecated use the `minTaskCount` and `maxTaskCount` properties of `autoScaleTaskCount` in the `Service` construct + * to configure the auto scaling target for the service. For more information, please refer + * https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk-containers/ecs-service-extensions/README.md#task-auto-scaling . */ export interface CpuScalingProps { /** @@ -61,6 +66,9 @@ const cpuScalingPropsDefault = { /** * This extension helps you scale your service according to CPU utilization. + * + * @deprecated To enable target tracking based on CPU utilization, use the `targetCpuUtilization` property of `autoScaleTaskCount` in the `Service` construct. + * For more information, please refer https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk-containers/ecs-service-extensions/README.md#task-auto-scaling . */ export class ScaleOnCpuUtilization extends ServiceExtension { /** @@ -126,6 +134,9 @@ export class ScaleOnCpuUtilization extends ServiceExtension { // This hook utilizes the resulting service construct // once it is created. public useService(service: ecs.Ec2Service | ecs.FargateService) { + if (this.parentService.scalableTaskCount) { + throw Error('Cannot specify \'autoScaleTaskCount\' in the Service construct and also provide a \'ScaleOnCpuUtilization\' extension. \'ScaleOnCpuUtilization\' is deprecated. Please only provide \'autoScaleTaskCount\'.'); + } const scalingTarget = service.autoScaleTaskCount({ minCapacity: this.minTaskCount, maxCapacity: this.maxTaskCount, @@ -136,5 +147,6 @@ export class ScaleOnCpuUtilization extends ServiceExtension { scaleInCooldown: this.scaleInCooldown, scaleOutCooldown: this.scaleOutCooldown, }); + this.parentService.enableAutoScalingPolicy(); } } diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/lib/service.ts b/packages/@aws-cdk-containers/ecs-service-extensions/lib/service.ts index 2214f209fb935..c90c59edaea31 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/lib/service.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/lib/service.ts @@ -54,6 +54,8 @@ export interface ServiceProps { /** * The options for configuring the auto scaling target. + * + * @default none */ readonly autoScaleTaskCount?: AutoScalingOptions; } @@ -196,7 +198,6 @@ export class Service extends Construct { // Ensure that the task definition supports both EC2 and Fargate compatibility: ecs.Compatibility.EC2_AND_FARGATE, } as ecs.TaskDefinitionProps; - for (const extensions in this.serviceDescription.extensions) { if (this.serviceDescription.extensions[extensions]) { taskDefProps = this.serviceDescription.extensions[extensions].modifyTaskDefinitionProps(taskDefProps); @@ -221,9 +222,6 @@ export class Service extends Construct { } } - // Set desiredCount to `undefined` if auto scaling is configured for the service - const desiredCount = props.autoScaleTaskCount ? undefined : (props.desiredCount || 1); - // Give each extension a chance to mutate the service props before // service creation let serviceProps = { @@ -231,7 +229,7 @@ export class Service extends Construct { taskDefinition: this.taskDefinition, minHealthyPercent: 100, maxHealthyPercent: 200, - desiredCount, + desiredCount: props.desiredCount ?? 1, } as ServiceBuild; for (const extensions in this.serviceDescription.extensions) { @@ -273,6 +271,14 @@ export class Service extends Construct { } } + // Set desiredCount to `undefined` if auto scaling is configured for the service + if (props.autoScaleTaskCount || this.autoScalingPoliciesEnabled) { + serviceProps = { + ...serviceProps, + desiredCount: undefined, + }; + } + // Now that the service props are determined we can create // the service if (this.capacityType === EnvironmentCapacityType.EC2) { @@ -291,17 +297,17 @@ export class Service extends Construct { }); if (props.autoScaleTaskCount.targetCpuUtilization) { - const targetUtilizationPercent = props.autoScaleTaskCount.targetCpuUtilization; - this.scalableTaskCount.scaleOnCpuUtilization(`${this.id}-target-cpu-utilization-${targetUtilizationPercent}`, { - targetUtilizationPercent, + const targetCpuUtilizationPercent = props.autoScaleTaskCount.targetCpuUtilization; + this.scalableTaskCount.scaleOnCpuUtilization(`${this.id}-target-cpu-utilization-${targetCpuUtilizationPercent}`, { + targetUtilizationPercent: targetCpuUtilizationPercent, }); this.enableAutoScalingPolicy(); } if (props.autoScaleTaskCount.targetMemoryUtilization) { - const targetUtilizationPercent = props.autoScaleTaskCount.targetMemoryUtilization; - this.scalableTaskCount.scaleOnMemoryUtilization(`${this.id}-target-memory-utilization-${targetUtilizationPercent}`, { - targetUtilizationPercent, + const targetMemoryUtilizationPercent = props.autoScaleTaskCount.targetMemoryUtilization; + this.scalableTaskCount.scaleOnMemoryUtilization(`${this.id}-target-memory-utilization-${targetMemoryUtilizationPercent}`, { + targetUtilizationPercent: targetMemoryUtilizationPercent, }); this.enableAutoScalingPolicy(); } diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/package.json b/packages/@aws-cdk-containers/ecs-service-extensions/package.json index 6fad145eafd8c..e59612c4d6b3d 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/package.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/package.json @@ -70,6 +70,7 @@ "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/custom-resources": "0.0.0", + "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69" }, @@ -98,6 +99,7 @@ "@aws-cdk/aws-sqs": "0.0.0", "@aws-cdk/core": "0.0.0", "@aws-cdk/custom-resources": "0.0.0", + "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69" }, diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/appmesh.test.ts b/packages/@aws-cdk-containers/ecs-service-extensions/test/appmesh.test.ts index 64ec202869f73..0d54e8e43570f 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/appmesh.test.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/appmesh.test.ts @@ -2,7 +2,7 @@ import '@aws-cdk/assert-internal/jest'; import * as appmesh from '@aws-cdk/aws-appmesh'; import * as ecs from '@aws-cdk/aws-ecs'; import * as cdk from '@aws-cdk/core'; -import { AppMeshExtension, Container, Environment, ScaleOnCpuUtilization, ServiceDescription, Service } from '../lib'; +import { AppMeshExtension, Container, Environment, ServiceDescription, Service } from '../lib'; describe('appmesh', () => { test('should be able to add AWS App Mesh to a service', () => { @@ -33,7 +33,6 @@ describe('appmesh', () => { }); // THEN - // Ensure that task has an App Mesh sidecar expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ @@ -276,9 +275,6 @@ describe('appmesh', () => { trafficPort: 80, image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), })); - serviceDescription.add(new ScaleOnCpuUtilization({ - initialTaskCount: 1, - })); const mesh = new appmesh.Mesh(stack, 'my-mesh'); @@ -289,6 +285,7 @@ describe('appmesh', () => { new Service(stack, 'my-service', { environment, serviceDescription, + desiredCount: 1, }); expect(stack).toHaveResourceLike('AWS::ECS::Service', { @@ -317,9 +314,6 @@ describe('appmesh', () => { trafficPort: 80, image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), })); - serviceDescription.add(new ScaleOnCpuUtilization({ - initialTaskCount: 2, - })); const mesh = new appmesh.Mesh(stack, 'my-mesh'); @@ -330,6 +324,7 @@ describe('appmesh', () => { new Service(stack, 'my-service', { environment, serviceDescription, + desiredCount: 2, }); expect(stack).toHaveResourceLike('AWS::ECS::Service', { @@ -358,9 +353,6 @@ describe('appmesh', () => { trafficPort: 80, image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), })); - serviceDescription.add(new ScaleOnCpuUtilization({ - initialTaskCount: 3, - })); const mesh = new appmesh.Mesh(stack, 'my-mesh'); @@ -371,6 +363,7 @@ describe('appmesh', () => { new Service(stack, 'my-service', { environment, serviceDescription, + desiredCount: 3, }); expect(stack).toHaveResourceLike('AWS::ECS::Service', { @@ -399,9 +392,6 @@ describe('appmesh', () => { trafficPort: 80, image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), })); - serviceDescription.add(new ScaleOnCpuUtilization({ - initialTaskCount: 4, - })); const mesh = new appmesh.Mesh(stack, 'my-mesh'); @@ -412,6 +402,7 @@ describe('appmesh', () => { new Service(stack, 'my-service', { environment, serviceDescription, + desiredCount: 4, }); expect(stack).toHaveResourceLike('AWS::ECS::Service', { @@ -440,9 +431,6 @@ describe('appmesh', () => { trafficPort: 80, image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), })); - serviceDescription.add(new ScaleOnCpuUtilization({ - initialTaskCount: 8, - })); const mesh = new appmesh.Mesh(stack, 'my-mesh'); @@ -453,6 +441,7 @@ describe('appmesh', () => { new Service(stack, 'my-service', { environment, serviceDescription, + desiredCount: 8, }); expect(stack).toHaveResourceLike('AWS::ECS::Service', { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/cloudwatch-agent.test.ts b/packages/@aws-cdk-containers/ecs-service-extensions/test/cloudwatch-agent.test.ts index 08cd8dfbe8a04..d9ff4f3b50fae 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/cloudwatch-agent.test.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/cloudwatch-agent.test.ts @@ -27,7 +27,6 @@ describe('cloudwatch agent', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/container.test.ts b/packages/@aws-cdk-containers/ecs-service-extensions/test/container.test.ts new file mode 100644 index 0000000000000..3e9b2e79dd9e8 --- /dev/null +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/container.test.ts @@ -0,0 +1,316 @@ +import '@aws-cdk/assert-internal/jest'; +import * as autoscaling from '@aws-cdk/aws-autoscaling'; +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as ecs from '@aws-cdk/aws-ecs'; +import * as iam from '@aws-cdk/aws-iam'; +import * as awslogs from '@aws-cdk/aws-logs'; +import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; +import { Container, Environment, EnvironmentCapacityType, FireLensExtension, Service, ServiceDescription } from '../lib'; + +describe('container', () => { + test('should be able to add a container to the service', () => { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addAsgCapacityProvider(new ecs.AsgCapacityProvider(stack, 'Provider', { + autoScalingGroup: new autoscaling.AutoScalingGroup(stack, 'DefaultAutoScalingGroup', { + vpc, + machineImage: ec2.MachineImage.latestAmazonLinux(), + instanceType: new ec2.InstanceType('t2.micro'), + }), + })); + + const environment = new Environment(stack, 'production', { + vpc, + cluster, + capacityType: EnvironmentCapacityType.EC2, + }); + const serviceDescription = new ServiceDescription(); + const taskRole = new iam.Role(stack, 'CustomTaskRole', { + assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), + }); + + serviceDescription.add(new Container({ + cpu: 256, + memoryMiB: 512, + trafficPort: 80, + image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), + })); + + new Service(stack, 'my-service', { + environment, + serviceDescription, + taskRole, + }); + + // THEN + expect(stack).toCountResources('AWS::ECS::Service', 1); + + expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + { + Cpu: 256, + Essential: true, + Image: 'nathanpeck/name', + Memory: 512, + Name: 'app', + PortMappings: [ + { + ContainerPort: 80, + Protocol: 'tcp', + }, + ], + Ulimits: [ + { + HardLimit: 1024000, + Name: 'nofile', + SoftLimit: 1024000, + }, + ], + }, + ], + Cpu: '256', + Family: 'myservicetaskdefinition', + Memory: '512', + NetworkMode: 'awsvpc', + RequiresCompatibilities: [ + 'EC2', + 'FARGATE', + ], + TaskRoleArn: { + 'Fn::GetAtt': [ + 'CustomTaskRole3C6B13FD', + 'Arn', + ], + }, + }); + + + }); + + test('should be able to enable default logging behavior - with enable default log driver feature flag', () => { + // GIVEN + const stack = new cdk.Stack(); + stack.node.setContext(cxapi.ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER, true); + + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addAsgCapacityProvider(new ecs.AsgCapacityProvider(stack, 'Provider', { + autoScalingGroup: new autoscaling.AutoScalingGroup(stack, 'DefaultAutoScalingGroup', { + vpc, + machineImage: ec2.MachineImage.latestAmazonLinux(), + instanceType: new ec2.InstanceType('t2.micro'), + }), + })); + + const environment = new Environment(stack, 'production', { + vpc, + cluster, + capacityType: EnvironmentCapacityType.EC2, + }); + const serviceDescription = new ServiceDescription(); + const taskRole = new iam.Role(stack, 'CustomTaskRole', { + assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), + }); + + serviceDescription.add(new Container({ + cpu: 256, + memoryMiB: 512, + trafficPort: 80, + image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), + })); + + new Service(stack, 'my-service', { + environment, + serviceDescription, + taskRole, + }); + + // THEN + expect(stack).toCountResources('AWS::ECS::Service', 1); + + // Ensure that the log group was created + expect(stack).toHaveResource('AWS::Logs::LogGroup'); + + expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + { + Cpu: 256, + Essential: true, + Image: 'nathanpeck/name', + LogConfiguration: { + LogDriver: 'awslogs', + Options: { + 'awslogs-group': { + Ref: 'myservicelogs176EE19F', + }, + 'awslogs-stream-prefix': 'my-service', + 'awslogs-region': { + Ref: 'AWS::Region', + }, + }, + }, + Memory: 512, + Name: 'app', + PortMappings: [ + { + ContainerPort: 80, + Protocol: 'tcp', + }, + ], + Ulimits: [ + { + HardLimit: 1024000, + Name: 'nofile', + SoftLimit: 1024000, + }, + ], + }, + ], + Cpu: '256', + Family: 'myservicetaskdefinition', + Memory: '512', + NetworkMode: 'awsvpc', + RequiresCompatibilities: [ + 'EC2', + 'FARGATE', + ], + TaskRoleArn: { + 'Fn::GetAtt': [ + 'CustomTaskRole3C6B13FD', + 'Arn', + ], + }, + }); + + + }); + + test('should be able to add user-provided log group in the log driver options', () => { + // GIVEN + const stack = new cdk.Stack(); + stack.node.setContext(cxapi.ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER, true); + + const vpc = new ec2.Vpc(stack, 'VPC'); + const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); + cluster.addAsgCapacityProvider(new ecs.AsgCapacityProvider(stack, 'Provider', { + autoScalingGroup: new autoscaling.AutoScalingGroup(stack, 'DefaultAutoScalingGroup', { + vpc, + machineImage: ec2.MachineImage.latestAmazonLinux(), + instanceType: new ec2.InstanceType('t2.micro'), + }), + })); + + const environment = new Environment(stack, 'production', { + vpc, + cluster, + capacityType: EnvironmentCapacityType.EC2, + }); + const serviceDescription = new ServiceDescription(); + const taskRole = new iam.Role(stack, 'CustomTaskRole', { + assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), + }); + + serviceDescription.add(new Container({ + cpu: 256, + memoryMiB: 512, + trafficPort: 80, + image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), + logGroup: new awslogs.LogGroup(stack, 'MyLogGroup'), + })); + + new Service(stack, 'my-service', { + environment, + serviceDescription, + taskRole, + }); + + // THEN + expect(stack).toCountResources('AWS::ECS::Service', 1); + + // Ensure that the log group was created + expect(stack).toHaveResource('AWS::Logs::LogGroup'); + + expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + { + Cpu: 256, + Essential: true, + Image: 'nathanpeck/name', + LogConfiguration: { + LogDriver: 'awslogs', + Options: { + 'awslogs-group': { + Ref: 'MyLogGroup5C0DAD85', + }, + 'awslogs-stream-prefix': 'my-service', + 'awslogs-region': { + Ref: 'AWS::Region', + }, + }, + }, + Memory: 512, + Name: 'app', + PortMappings: [ + { + ContainerPort: 80, + Protocol: 'tcp', + }, + ], + Ulimits: [ + { + HardLimit: 1024000, + Name: 'nofile', + SoftLimit: 1024000, + }, + ], + }, + ], + Cpu: '256', + Family: 'myservicetaskdefinition', + Memory: '512', + NetworkMode: 'awsvpc', + RequiresCompatibilities: [ + 'EC2', + 'FARGATE', + ], + TaskRoleArn: { + 'Fn::GetAtt': [ + 'CustomTaskRole3C6B13FD', + 'Arn', + ], + }, + }); + + + }); + + test('should error when log group is provided in the container extension and another observability extension is added', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const environment = new Environment(stack, 'production'); + const serviceDescription = new ServiceDescription(); + + serviceDescription.add(new Container({ + cpu: 256, + memoryMiB: 512, + trafficPort: 80, + image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), + logGroup: new awslogs.LogGroup(stack, 'MyLogGroup'), + })); + serviceDescription.add(new FireLensExtension()); + + // THEN + expect(() => { + new Service(stack, 'my-service', { + environment, + serviceDescription, + }); + }).toThrow(/Log configuration already specified. You cannot provide a log group for the application container of service 'my-service' while also adding log configuration separately using service extensions./); + }); + +}); diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json index faee3f71397ab..556524b695267 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.assign-public-ip.expected.json @@ -291,6 +291,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "namelogsF4B17D31" + }, + "awslogs-stream-prefix": "name", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 512, "Name": "app", "PortMappings": [ @@ -309,6 +321,12 @@ } ], "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "nametaskdefinitionExecutionRole45AC5C9A", + "Arn" + ] + }, "Family": "awsecsintegnametaskdefinition0EA6A1A0", "Memory": "512", "NetworkMode": "awsvpc", @@ -329,6 +347,71 @@ "nameserviceTaskRecordManagerRuleStopped66D08B70" ] }, + "nametaskdefinitionExecutionRole45AC5C9A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + }, + "DependsOn": [ + "nameserviceTaskRecordManagerCleanupE19F1043", + "nameserviceTaskRecordManagerRuleRunningCD85F46F", + "nameserviceTaskRecordManagerRuleStopped66D08B70" + ] + }, + "nametaskdefinitionExecutionRoleDefaultPolicyF7942D20": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "namelogsF4B17D31", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "nametaskdefinitionExecutionRoleDefaultPolicyF7942D20", + "Roles": [ + { + "Ref": "nametaskdefinitionExecutionRole45AC5C9A" + } + ] + }, + "DependsOn": [ + "nameserviceTaskRecordManagerCleanupE19F1043", + "nameserviceTaskRecordManagerRuleRunningCD85F46F", + "nameserviceTaskRecordManagerRuleStopped66D08B70" + ] + }, + "namelogsF4B17D31": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "name-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "nameserviceService8015C8D6": { "Type": "AWS::ECS::Service", "Properties": { @@ -714,7 +797,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3Bucket1AECFCFD" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3Bucket1E7F92B6" }, "S3Key": { "Fn::Join": [ @@ -727,7 +810,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3VersionKey2ACFB47F" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3VersionKey86FCA825" } ] } @@ -740,7 +823,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3VersionKey2ACFB47F" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3VersionKey86FCA825" } ] } @@ -877,7 +960,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3Bucket1AECFCFD" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3Bucket1E7F92B6" }, "S3Key": { "Fn::Join": [ @@ -890,7 +973,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3VersionKey2ACFB47F" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3VersionKey86FCA825" } ] } @@ -903,7 +986,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3VersionKey2ACFB47F" + "Ref": "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3VersionKey86FCA825" } ] } @@ -1190,7 +1273,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2S3BucketF482197E" + "Ref": "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87S3Bucket36F31A16" }, "S3Key": { "Fn::Join": [ @@ -1203,7 +1286,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2S3VersionKey38B69632" + "Ref": "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87S3VersionKeyF80D542B" } ] } @@ -1216,7 +1299,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2S3VersionKey38B69632" + "Ref": "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87S3VersionKeyF80D542B" } ] } @@ -1242,17 +1325,17 @@ } }, "Parameters": { - "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3Bucket1AECFCFD": { + "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3Bucket1E7F92B6": { "Type": "String", - "Description": "S3 bucket for asset \"1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3e\"" + "Description": "S3 bucket for asset \"8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725d\"" }, - "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eS3VersionKey2ACFB47F": { + "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dS3VersionKey86FCA825": { "Type": "String", - "Description": "S3 key for asset version \"1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3e\"" + "Description": "S3 key for asset version \"8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725d\"" }, - "AssetParameters1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3eArtifactHashC1CF90D5": { + "AssetParameters8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725dArtifactHash0F81F2AB": { "Type": "String", - "Description": "Artifact hash for asset \"1cd4a64795df8938c7ff3d71caa4b3fd27d3d5caa222517813b08ae2a6494d3e\"" + "Description": "Artifact hash for asset \"8f06a3db22794ebc7ff89b4745fd706afd46e17816fe46da72e5125cabae725d\"" }, "AssetParametersdaeb79e3cee39c9b902dc0d5c780223e227ed573ea60976252947adab5fb2be1S3BucketDC4B98B1": { "Type": "String", @@ -1266,17 +1349,17 @@ "Type": "String", "Description": "Artifact hash for asset \"daeb79e3cee39c9b902dc0d5c780223e227ed573ea60976252947adab5fb2be1\"" }, - "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2S3BucketF482197E": { + "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87S3Bucket36F31A16": { "Type": "String", - "Description": "S3 bucket for asset \"6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2\"" + "Description": "S3 bucket for asset \"3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87\"" }, - "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2S3VersionKey38B69632": { + "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87S3VersionKeyF80D542B": { "Type": "String", - "Description": "S3 key for asset version \"6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2\"" + "Description": "S3 key for asset version \"3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87\"" }, - "AssetParameters6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2ArtifactHash4BE92B79": { + "AssetParameters3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87ArtifactHash40DDF5EE": { "Type": "String", - "Description": "Artifact hash for asset \"6ee0a36dd10d630708c265bcf7616c64030040c1bbc383b34150db74b744cad2\"" + "Description": "Artifact hash for asset \"3744fa896361f81b76b1efde632ac07b1920ce09a4ca1ff15ab486f262a19b87\"" } }, "Outputs": { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.custom-service-extension.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.custom-service-extension.expected.json index 5fbaf177162df..af4f8829a1501 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.custom-service-extension.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.custom-service-extension.expected.json @@ -548,6 +548,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "namelogsF4B17D31" + }, + "awslogs-stream-prefix": "name", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 2048, "Name": "app", "PortMappings": [ @@ -566,6 +578,12 @@ } ], "Cpu": "1024", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "nametaskdefinitionExecutionRole45AC5C9A", + "Arn" + ] + }, "Family": "awsecsintegnametaskdefinition0EA6A1A0", "Memory": "2048", "NetworkMode": "awsvpc", @@ -581,6 +599,61 @@ } } }, + "nametaskdefinitionExecutionRole45AC5C9A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "nametaskdefinitionExecutionRoleDefaultPolicyF7942D20": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "namelogsF4B17D31", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "nametaskdefinitionExecutionRoleDefaultPolicyF7942D20", + "Roles": [ + { + "Ref": "nametaskdefinitionExecutionRole45AC5C9A" + } + ] + } + }, + "namelogsF4B17D31": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "name-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "nameserviceService8015C8D6": { "Type": "AWS::ECS::Service", "Properties": { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json index c85f5d9b0231d..48775db8f3c84 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.imported-environment.expected.json @@ -209,6 +209,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "Servicelogs9F4E1F70" + }, + "awslogs-stream-prefix": "Service", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 512, "Name": "app", "PortMappings": [ @@ -227,6 +239,12 @@ } ], "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "ServicetaskdefinitionExecutionRoleD09F4578", + "Arn" + ] + }, "Family": "importedenvironmentintegServicetaskdefinition63936B87", "Memory": "512", "NetworkMode": "awsvpc", @@ -242,6 +260,61 @@ } } }, + "ServicetaskdefinitionExecutionRoleD09F4578": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "ServicetaskdefinitionExecutionRoleDefaultPolicy25CEAFC5": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Servicelogs9F4E1F70", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "ServicetaskdefinitionExecutionRoleDefaultPolicy25CEAFC5", + "Roles": [ + { + "Ref": "ServicetaskdefinitionExecutionRoleD09F4578" + } + ] + } + }, + "Servicelogs9F4E1F70": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "Service-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "ServiceserviceService6A153CB8": { "Type": "AWS::ECS::Service", "Properties": { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json index 91ce21c4a2c5f..fa97c69cefc1c 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.multiple-environments.expected.json @@ -1103,6 +1103,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "nameproductionlogsD0BFFE8C" + }, + "awslogs-stream-prefix": "name-production", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 2048, "Name": "app", "PortMappings": [ @@ -1266,11 +1278,6 @@ } } }, - "nameproductiontaskdefinitionenvoyLogGroupF79A2732": { - "Type": "AWS::Logs::LogGroup", - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" - }, "nameproductiontaskdefinitionExecutionRoleB72DD86B": { "Type": "AWS::IAM::Role", "Properties": { @@ -1293,6 +1300,19 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "nameproductionlogsD0BFFE8C", + "Arn" + ] + } + }, { "Action": [ "ecr:BatchCheckLayerAvailability", @@ -1356,6 +1376,20 @@ ] } }, + "nameproductiontaskdefinitionenvoyLogGroupF79A2732": { + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "nameproductionlogsD0BFFE8C": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "name-production-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "nameproductionenvoytoappmesh1B44B04A": { "Type": "AWS::IAM::Policy", "Properties": { @@ -1631,6 +1665,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "namedevelopmentlogs108670CC" + }, + "awslogs-stream-prefix": "name-development", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 2048, "Name": "app", "PortMappings": [ @@ -1794,11 +1840,6 @@ } } }, - "namedevelopmenttaskdefinitionenvoyLogGroupF8FCAFD6": { - "Type": "AWS::Logs::LogGroup", - "UpdateReplacePolicy": "Retain", - "DeletionPolicy": "Retain" - }, "namedevelopmenttaskdefinitionExecutionRole48B53E4E": { "Type": "AWS::IAM::Role", "Properties": { @@ -1821,6 +1862,19 @@ "Properties": { "PolicyDocument": { "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "namedevelopmentlogs108670CC", + "Arn" + ] + } + }, { "Action": [ "ecr:BatchCheckLayerAvailability", @@ -1884,6 +1938,20 @@ ] } }, + "namedevelopmenttaskdefinitionenvoyLogGroupF8FCAFD6": { + "Type": "AWS::Logs::LogGroup", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "namedevelopmentlogs108670CC": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "name-development-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "namedevelopmentenvoytoappmesh45FF08AA": { "Type": "AWS::IAM::Policy", "Properties": { diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.publish-subscribe.expected.json b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.publish-subscribe.expected.json index 465a7ce4b3374..24cd1d0a4e434 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.publish-subscribe.expected.json +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/integ.publish-subscribe.expected.json @@ -596,6 +596,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "PublisherlogsDF0C1067" + }, + "awslogs-stream-prefix": "Publisher", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 512, "Name": "app", "PortMappings": [ @@ -614,6 +626,12 @@ } ], "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "PublishertaskdefinitionExecutionRole5C00C542", + "Arn" + ] + }, "Family": "awsecsintegPublishertaskdefinitionD50610D0", "Memory": "512", "NetworkMode": "awsvpc", @@ -629,6 +647,61 @@ } } }, + "PublishertaskdefinitionExecutionRole5C00C542": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "PublishertaskdefinitionExecutionRoleDefaultPolicy681FD8E6": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "PublisherlogsDF0C1067", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "PublishertaskdefinitionExecutionRoleDefaultPolicy681FD8E6", + "Roles": [ + { + "Ref": "PublishertaskdefinitionExecutionRole5C00C542" + } + ] + } + }, + "PublisherlogsDF0C1067": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "Publisher-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "PublisherserviceService9EB00F60": { "Type": "AWS::ECS::Service", "Properties": { @@ -901,6 +974,18 @@ ], "Essential": true, "Image": "nathanpeck/name", + "LogConfiguration": { + "LogDriver": "awslogs", + "Options": { + "awslogs-group": { + "Ref": "Workerlogs2994AC4D" + }, + "awslogs-stream-prefix": "Worker", + "awslogs-region": { + "Ref": "AWS::Region" + } + } + }, "Memory": 512, "Name": "app", "PortMappings": [ @@ -919,6 +1004,12 @@ } ], "Cpu": "256", + "ExecutionRoleArn": { + "Fn::GetAtt": [ + "WorkertaskdefinitionExecutionRole3C1A1848", + "Arn" + ] + }, "Family": "awsecsintegWorkertaskdefinition32B60762", "Memory": "512", "NetworkMode": "awsvpc", @@ -934,6 +1025,61 @@ } } }, + "WorkertaskdefinitionExecutionRole3C1A1848": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ecs-tasks.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "WorkertaskdefinitionExecutionRoleDefaultPolicy6E199B19": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Workerlogs2994AC4D", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "WorkertaskdefinitionExecutionRoleDefaultPolicy6E199B19", + "Roles": [ + { + "Ref": "WorkertaskdefinitionExecutionRole3C1A1848" + } + ] + } + }, + "Workerlogs2994AC4D": { + "Type": "AWS::Logs::LogGroup", + "Properties": { + "LogGroupName": "Worker-logs", + "RetentionInDays": 30 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, "WorkerserviceService68C5A5C3": { "Type": "AWS::ECS::Service", "Properties": { @@ -1184,7 +1330,7 @@ "Properties": { "Code": { "S3Bucket": { - "Ref": "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dS3Bucket151170D5" + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3Bucket1FFDEA8D" }, "S3Key": { "Fn::Join": [ @@ -1197,7 +1343,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dS3VersionKey3D692C3D" + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B" } ] } @@ -1210,7 +1356,7 @@ "Fn::Split": [ "||", { - "Ref": "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dS3VersionKey3D692C3D" + "Ref": "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B" } ] } @@ -1326,17 +1472,17 @@ } }, "Parameters": { - "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dS3Bucket151170D5": { + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3Bucket1FFDEA8D": { "Type": "String", - "Description": "S3 bucket for asset \"cc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19d\"" + "Description": "S3 bucket for asset \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" }, - "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dS3VersionKey3D692C3D": { + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91S3VersionKeyA60C027B": { "Type": "String", - "Description": "S3 key for asset version \"cc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19d\"" + "Description": "S3 key for asset version \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" }, - "AssetParameterscc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19dArtifactHash167B1C30": { + "AssetParametersa820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91ArtifactHashC1953821": { "Type": "String", - "Description": "Artifact hash for asset \"cc8d03e1cef62b38b47438d429cdc3828f57a52cffd1a84c4cda032bc21be19d\"" + "Description": "Artifact hash for asset \"a820140ad8525b8ed56ad2a7bcd9da99d6afc2490e8c91e34620886c011bdc91\"" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/scale-on-cpu-utilization.test.ts b/packages/@aws-cdk-containers/ecs-service-extensions/test/scale-on-cpu-utilization.test.ts index 1b8c9f82fb1a6..561e1f7991a94 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/scale-on-cpu-utilization.test.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/scale-on-cpu-utilization.test.ts @@ -149,4 +149,32 @@ describe('scale on cpu utilization', () => { }); + test('should error if configuring autoscaling target both in the extension and the Service', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + const environment = new Environment(stack, 'production'); + const serviceDescription = new ServiceDescription(); + + serviceDescription.add(new Container({ + cpu: 256, + memoryMiB: 512, + trafficPort: 80, + image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), + })); + + serviceDescription.add(new ScaleOnCpuUtilization()); + // THEN + expect(() => { + new Service(stack, 'my-service', { + environment, + serviceDescription, + autoScaleTaskCount: { + maxTaskCount: 5, + }, + }); + }).toThrow('Cannot specify \'autoScaleTaskCount\' in the Service construct and also provide a \'ScaleOnCpuUtilization\' extension. \'ScaleOnCpuUtilization\' is deprecated. Please only provide \'autoScaleTaskCount\'.'); + }); + }); \ No newline at end of file diff --git a/packages/@aws-cdk-containers/ecs-service-extensions/test/service.test.ts b/packages/@aws-cdk-containers/ecs-service-extensions/test/service.test.ts index 39d26ef371f17..8db284b856e28 100644 --- a/packages/@aws-cdk-containers/ecs-service-extensions/test/service.test.ts +++ b/packages/@aws-cdk-containers/ecs-service-extensions/test/service.test.ts @@ -1,11 +1,8 @@ import { ABSENT } from '@aws-cdk/assert-internal'; import '@aws-cdk/assert-internal/jest'; -import * as autoscaling from '@aws-cdk/aws-autoscaling'; -import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; -import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; -import { Container, EnvironmentCapacityType, Environment, Service, ServiceDescription } from '../lib'; +import { Container, Environment, Service, ServiceDescription } from '../lib'; describe('service', () => { test('should error if a service is prepared with no addons', () => { @@ -25,87 +22,6 @@ describe('service', () => { }).toThrow(/Service 'my-service' must have a Container extension/); - }); - - test('should be able to add a container to the service', () => { - // GIVEN - const stack = new cdk.Stack(); - const vpc = new ec2.Vpc(stack, 'VPC'); - const cluster = new ecs.Cluster(stack, 'Cluster', { vpc }); - cluster.addAsgCapacityProvider(new ecs.AsgCapacityProvider(stack, 'Provider', { - autoScalingGroup: new autoscaling.AutoScalingGroup(stack, 'DefaultAutoScalingGroup', { - vpc, - machineImage: ec2.MachineImage.latestAmazonLinux(), - instanceType: new ec2.InstanceType('t2.micro'), - }), - })); - - const environment = new Environment(stack, 'production', { - vpc, - cluster, - capacityType: EnvironmentCapacityType.EC2, - }); - const serviceDescription = new ServiceDescription(); - const taskRole = new iam.Role(stack, 'CustomTaskRole', { - assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), - }); - - serviceDescription.add(new Container({ - cpu: 256, - memoryMiB: 512, - trafficPort: 80, - image: ecs.ContainerImage.fromRegistry('nathanpeck/name'), - })); - - new Service(stack, 'my-service', { - environment, - serviceDescription, - taskRole, - }); - - // THEN - expect(stack).toCountResources('AWS::ECS::Service', 1); - - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { - ContainerDefinitions: [ - { - Cpu: 256, - Essential: true, - Image: 'nathanpeck/name', - Memory: 512, - Name: 'app', - PortMappings: [ - { - ContainerPort: 80, - Protocol: 'tcp', - }, - ], - Ulimits: [ - { - HardLimit: 1024000, - Name: 'nofile', - SoftLimit: 1024000, - }, - ], - }, - ], - Cpu: '256', - Family: 'myservicetaskdefinition', - Memory: '512', - NetworkMode: 'awsvpc', - RequiresCompatibilities: [ - 'EC2', - 'FARGATE', - ], - TaskRoleArn: { - 'Fn::GetAtt': [ - 'CustomTaskRole3C6B13FD', - 'Arn', - ], - }, - }); - - }); test('allows scaling on a target CPU utilization', () => { diff --git a/packages/@aws-cdk/app-delivery/package.json b/packages/@aws-cdk/app-delivery/package.json index 1f38f68a69a1b..cb1e48d089632 100644 --- a/packages/@aws-cdk/app-delivery/package.json +++ b/packages/@aws-cdk/app-delivery/package.json @@ -66,7 +66,7 @@ "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", - "fast-check": "^2.20.0", + "fast-check": "^2.21.0", "jest": "^27.4.7" }, "repository": { diff --git a/packages/@aws-cdk/assertions/lib/private/parameters.ts b/packages/@aws-cdk/assertions/lib/private/parameters.ts new file mode 100644 index 0000000000000..b708460caf399 --- /dev/null +++ b/packages/@aws-cdk/assertions/lib/private/parameters.ts @@ -0,0 +1,30 @@ +import { filterLogicalId, formatFailure, matchSection } from './section'; +import { Template } from './template'; + +export function findParameters(template: Template, logicalId: string, props: any = {}): { [key: string]: { [key: string]: any } } { + const section: { [key: string] : {} } = template.Parameters; + const result = matchSection(filterLogicalId(section, logicalId), props); + + if (!result.match) { + return {}; + } + + return result.matches; +} + +export function hasParameter(template: Template, logicalId: string, props: any): string | void { + const section: { [key: string] : {} } = template.Parameters; + const result = matchSection(filterLogicalId(section, logicalId), props); + if (result.match) { + return; + } + + if (result.closestResult === undefined) { + return 'No parameters found in the template'; + } + + return [ + `Template has ${result.analyzedCount} parameters, but none match as expected.`, + formatFailure(result.closestResult), + ].join('\n'); +} diff --git a/packages/@aws-cdk/assertions/lib/private/template.ts b/packages/@aws-cdk/assertions/lib/private/template.ts index 3b44368138435..72dbeb8b64661 100644 --- a/packages/@aws-cdk/assertions/lib/private/template.ts +++ b/packages/@aws-cdk/assertions/lib/private/template.ts @@ -3,7 +3,8 @@ export type Template = { Resources: { [logicalId: string]: Resource }, Outputs: { [logicalId: string]: Output }, - Mappings: { [logicalId: string]: Mapping } + Mappings: { [logicalId: string]: Mapping }, + Parameters: { [logicalId: string]: Parameter } } export type Resource = { @@ -13,4 +14,9 @@ export type Resource = { export type Output = { [key: string]: any }; -export type Mapping = { [key: string]: any }; \ No newline at end of file +export type Mapping = { [key: string]: any }; + +export type Parameter = { + Type: string; + [key: string]: any; +} \ No newline at end of file diff --git a/packages/@aws-cdk/assertions/lib/template.ts b/packages/@aws-cdk/assertions/lib/template.ts index dfc830cf8d822..631c9f7137dc4 100644 --- a/packages/@aws-cdk/assertions/lib/template.ts +++ b/packages/@aws-cdk/assertions/lib/template.ts @@ -5,6 +5,7 @@ import { Match } from './match'; import { Matcher } from './matcher'; import { findMappings, hasMapping } from './private/mappings'; import { findOutputs, hasOutput } from './private/outputs'; +import { findParameters, hasParameter } from './private/parameters'; import { countResources, findResources, hasResource, hasResourceProperties } from './private/resources'; import { Template as TemplateType } from './private/template'; @@ -108,6 +109,30 @@ export class Template { return findResources(this.template, type, props); } + /** + * Assert that a Parameter with the given properties exists in the CloudFormation template. + * By default, performs partial matching on the parameter, via the `Match.objectLike()`. + * To configure different behavior, use other matchers in the `Match` class. + * @param logicalId the name of the parameter. Provide `'*'` to match all parameters in the template. + * @param props the parameter as should be expected in the template. + */ + public hasParameter(logicalId: string, props: any): void { + const matchError = hasParameter(this.template, logicalId, props); + if (matchError) { + throw new Error(matchError); + } + } + + /** + * Get the set of matching Parameters that match the given properties in the CloudFormation template. + * @param logicalId the name of the parameter. Provide `'*'` to match all parameters in the template. + * @param props by default, matches all Parameters in the template. + * When a literal object is provided, performs a partial match via `Match.objectLike()`. + * Use the `Match` APIs to configure a different behaviour. */ + public findParameters(logicalId: string, props: any = {}): { [key: string]: { [key: string]: any } } { + return findParameters(this.template, logicalId, props); + } + /** * Assert that an Output with the given properties exists in the CloudFormation template. * By default, performs partial matching on the resource, via the `Match.objectLike()`. diff --git a/packages/@aws-cdk/assertions/test/template.test.ts b/packages/@aws-cdk/assertions/test/template.test.ts index f5068cede6265..dd8377892f405 100644 --- a/packages/@aws-cdk/assertions/test/template.test.ts +++ b/packages/@aws-cdk/assertions/test/template.test.ts @@ -1,4 +1,4 @@ -import { App, CfnMapping, CfnOutput, CfnResource, NestedStack, Stack } from '@aws-cdk/core'; +import { App, CfnMapping, CfnOutput, CfnParameter, CfnResource, NestedStack, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { Capture, Match, Template } from '../lib'; @@ -708,6 +708,156 @@ describe('Template', () => { }); }); + describe('findParameters', () => { + test('matching', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findParameters('*', { Type: 'String' }); + expect(result).toEqual({ + p1: { + Description: 'string parameter', + Type: 'String', + }, + }); + }); + + test('not matching', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findParameters('*', { Type: 'Number' }); + expect(Object.keys(result).length).toEqual(0); + }); + + test('matching with specific parameter name', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findParameters('p1', { Type: 'String' }); + expect(result).toEqual({ + p1: { + Description: 'string parameter', + Type: 'String', + }, + }); + }); + + test('not matching specific parameter name', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + const result = inspect.findParameters('p3', { Type: 'String' }); + expect(Object.keys(result).length).toEqual(0); + }); + }); + + describe('hasParameter', () => { + test('matching', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + expect(() => inspect.findParameters('p3', { Type: 'String' })).not.toThrow(); + }); + + test('not matching', (done) => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + expectToThrow( + () => inspect.hasParameter('*', { Type: 'CommaDelimitedList' }), + [ + /2 parameters/, + /Expected CommaDelimitedList but received String/, + ], + done, + ); + done(); + }); + + test('matching specific parameter name', () => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + expect(() => inspect.findParameters('p1', { Type: 'String' })).not.toThrow(); + }); + + test('not matching specific parameter name', (done) => { + const stack = new Stack(); + new CfnParameter(stack, 'p1', { + type: 'String', + description: 'string parameter', + }); + new CfnParameter(stack, 'p2', { + type: 'Number', + description: 'number parameter', + }); + + const inspect = Template.fromStack(stack); + expectToThrow( + () => inspect.hasParameter('p2', { Type: 'CommaDelimitedList' }), + [ + /1 parameter/, + /Expected CommaDelimitedList but received Number/, + ], + done, + ); + done(); + }); + }); + describe('findMappings', () => { test('matching', () => { const stack = new Stack(); diff --git a/packages/@aws-cdk/assets/package.json b/packages/@aws-cdk/assets/package.json index d0ce86e435218..7bac0d2b66d81 100644 --- a/packages/@aws-cdk/assets/package.json +++ b/packages/@aws-cdk/assets/package.json @@ -69,7 +69,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/assets/test/compat.test.ts b/packages/@aws-cdk/assets/test/compat.test.ts index 25afe6dd9411b..dfb3c3afd2daa 100644 --- a/packages/@aws-cdk/assets/test/compat.test.ts +++ b/packages/@aws-cdk/assets/test/compat.test.ts @@ -1,5 +1,4 @@ import { SymlinkFollowMode } from '@aws-cdk/core'; -import '@aws-cdk/assert-internal/jest'; import { FollowMode } from '../lib'; import { toSymlinkFollow } from '../lib/compat'; diff --git a/packages/@aws-cdk/assets/test/staging.test.ts b/packages/@aws-cdk/assets/test/staging.test.ts index bd924e434207b..8893c6451f2c1 100644 --- a/packages/@aws-cdk/assets/test/staging.test.ts +++ b/packages/@aws-cdk/assets/test/staging.test.ts @@ -3,7 +3,6 @@ import * as path from 'path'; import { describeDeprecated } from '@aws-cdk/cdk-build-tools'; import { App, Stack } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; -import '@aws-cdk/assert-internal/jest'; import { Staging } from '../lib'; describeDeprecated('staging', () => { diff --git a/packages/@aws-cdk/aws-acmpca/package.json b/packages/@aws-cdk/aws-acmpca/package.json index b4dd6cff2355b..360332a20d54e 100644 --- a/packages/@aws-cdk/aws-acmpca/package.json +++ b/packages/@aws-cdk/aws-acmpca/package.json @@ -74,7 +74,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/aws-acmpca/test/acmpca.test.ts b/packages/@aws-cdk/aws-acmpca/test/acmpca.test.ts index c4505ad966984..b7175f106094e 100644 --- a/packages/@aws-cdk/aws-acmpca/test/acmpca.test.ts +++ b/packages/@aws-cdk/aws-acmpca/test/acmpca.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-apigateway/lib/api-key.ts b/packages/@aws-cdk/aws-apigateway/lib/api-key.ts index c6dd3e8c44dbd..1852ab0a42ad1 100644 --- a/packages/@aws-cdk/aws-apigateway/lib/api-key.ts +++ b/packages/@aws-cdk/aws-apigateway/lib/api-key.ts @@ -165,7 +165,7 @@ export class ApiKey extends ApiKeyBase { const resource = new CfnApiKey(this, 'Resource', { customerId: props.customerId, description: props.description, - enabled: props.enabled || true, + enabled: props.enabled ?? true, generateDistinctId: props.generateDistinctId, name: this.physicalName, stageKeys: this.renderStageKeys(props.resources), diff --git a/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts b/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts index a929519d39c5a..3008568ce2de4 100644 --- a/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts +++ b/packages/@aws-cdk/aws-apigateway/test/api-key.test.ts @@ -17,10 +17,33 @@ describe('api key', () => { // should have an api key with no props defined. }); + + test('enabled flag is respected', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new apigateway.ApiKey(stack, 'my-api-key', { + enabled: false, + value: 'arandomstringwithmorethantwentycharacters', + }); + + // THEN + expect(stack).toHaveResource('AWS::ApiGateway::ApiKey', { + Enabled: false, + Value: 'arandomstringwithmorethantwentycharacters', + }); + }); + + test('specify props for apiKey', () => { // GIVEN const stack = new cdk.Stack(); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -61,7 +84,11 @@ describe('api key', () => { test('use an imported api key', () => { // GIVEN const stack = new cdk.Stack(); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -83,7 +110,11 @@ describe('api key', () => { // GIVEN const stack = new cdk.Stack(); const user = new iam.User(stack, 'User'); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -130,7 +161,11 @@ describe('api key', () => { // GIVEN const stack = new cdk.Stack(); const user = new iam.User(stack, 'User'); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -182,7 +217,11 @@ describe('api key', () => { // GIVEN const stack = new cdk.Stack(); const user = new iam.User(stack, 'User'); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -253,7 +292,11 @@ describe('api key', () => { test('only api key is created when rate limiting properties are not provided', () => { // GIVEN const stack = new cdk.Stack(); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN @@ -281,7 +324,11 @@ describe('api key', () => { test('api key and usage plan are created and linked when rate limiting properties are provided', () => { // GIVEN const stack = new cdk.Stack(); - const api = new apigateway.RestApi(stack, 'test-api', { cloudWatchRole: false, deploy: true, deployOptions: { stageName: 'test' } }); + const api = new apigateway.RestApi(stack, 'test-api', { + cloudWatchRole: false, + deploy: true, + deployOptions: { stageName: 'test' }, + }); api.root.addMethod('GET'); // api must have atleast one method. // WHEN diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts index 6bdce918195cf..2417fffe1610d 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/lambda.ts @@ -63,10 +63,10 @@ export class HttpLambdaIntegration extends HttpRouteIntegration { }); return { - type: HttpIntegrationType.LAMBDA_PROXY, + type: HttpIntegrationType.AWS_PROXY, uri: this.handler.functionArn, payloadFormatVersion: this.props.payloadFormatVersion ?? PayloadFormatVersion.VERSION_2_0, parameterMapping: this.props.parameterMapping, }; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/index.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/index.ts index 04a64da0c7540..9c6035e3957d4 100644 --- a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/index.ts +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/index.ts @@ -1 +1,2 @@ export * from './lambda'; +export * from './mock'; diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/mock.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/mock.ts new file mode 100644 index 0000000000000..9c7a83ece4538 --- /dev/null +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/lib/websocket/mock.ts @@ -0,0 +1,27 @@ +import { + WebSocketRouteIntegration, + WebSocketIntegrationType, + WebSocketRouteIntegrationConfig, + WebSocketRouteIntegrationBindOptions, +} from '@aws-cdk/aws-apigatewayv2'; + +/** + * Mock WebSocket Integration + */ +export class WebSocketMockIntegration extends WebSocketRouteIntegration { + + /** + * @param id id of the underlying integration construct + */ + constructor(id: string) { + super(id); + } + + bind(options: WebSocketRouteIntegrationBindOptions): WebSocketRouteIntegrationConfig { + options; + return { + type: WebSocketIntegrationType.MOCK, + uri: '', + }; + } +} diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.expected.json b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.expected.json new file mode 100644 index 0000000000000..dede3af2298b4 --- /dev/null +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.expected.json @@ -0,0 +1,108 @@ +{ + "Resources": { + "mywsapi32E6CE11": { + "Type": "AWS::ApiGatewayV2::Api", + "Properties": { + "Name": "mywsapi", + "ProtocolType": "WEBSOCKET", + "RouteSelectionExpression": "$request.body.action" + } + }, + "mywsapidefaultRouteDefaultIntegrationFFCB3BA9": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "mywsapi32E6CE11" + }, + "IntegrationType": "MOCK", + "IntegrationUri": "" + } + }, + "mywsapidefaultRouteE9382DF8": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "mywsapi32E6CE11" + }, + "RouteKey": "$default", + "AuthorizationType": "NONE", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "mywsapidefaultRouteDefaultIntegrationFFCB3BA9" + } + ] + ] + } + } + }, + "mywsapisendmessageRouteSendMessageIntegrationD29E12F9": { + "Type": "AWS::ApiGatewayV2::Integration", + "Properties": { + "ApiId": { + "Ref": "mywsapi32E6CE11" + }, + "IntegrationType": "MOCK", + "IntegrationUri": "" + } + }, + "mywsapisendmessageRouteAE873328": { + "Type": "AWS::ApiGatewayV2::Route", + "Properties": { + "ApiId": { + "Ref": "mywsapi32E6CE11" + }, + "RouteKey": "sendmessage", + "AuthorizationType": "NONE", + "Target": { + "Fn::Join": [ + "", + [ + "integrations/", + { + "Ref": "mywsapisendmessageRouteSendMessageIntegrationD29E12F9" + } + ] + ] + } + } + }, + "mystage114C35EC": { + "Type": "AWS::ApiGatewayV2::Stage", + "Properties": { + "ApiId": { + "Ref": "mywsapi32E6CE11" + }, + "StageName": "dev", + "AutoDeploy": true + } + } + }, + "Outputs": { + "ApiEndpoint": { + "Value": { + "Fn::Join": [ + "", + [ + "wss://", + { + "Ref": "mywsapi32E6CE11" + }, + ".execute-api.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/dev" + ] + ] + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.ts new file mode 100644 index 0000000000000..672378b42d375 --- /dev/null +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/integ.mock.ts @@ -0,0 +1,24 @@ +import { WebSocketApi, WebSocketStage } from '@aws-cdk/aws-apigatewayv2'; +import { App, CfnOutput, Stack } from '@aws-cdk/core'; +import { WebSocketMockIntegration } from '../../lib'; + +/* + * Stack verification steps: + * 1. Verify manually that the integration has type "MOCK" + */ + +const app = new App(); +const stack = new Stack(app, 'integ-mock-websocket-integration'); + +const webSocketApi = new WebSocketApi(stack, 'mywsapi', { + defaultRouteOptions: { integration: new WebSocketMockIntegration('DefaultIntegration') }, +}); +const stage = new WebSocketStage(stack, 'mystage', { + webSocketApi, + stageName: 'dev', + autoDeploy: true, +}); + +webSocketApi.addRoute('sendmessage', { integration: new WebSocketMockIntegration('SendMessageIntegration') }); + +new CfnOutput(stack, 'ApiEndpoint', { value: stage.url }); diff --git a/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/mock.test.ts b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/mock.test.ts new file mode 100644 index 0000000000000..4bd7eccd9fc7b --- /dev/null +++ b/packages/@aws-cdk/aws-apigatewayv2-integrations/test/websocket/mock.test.ts @@ -0,0 +1,23 @@ +import { Template } from '@aws-cdk/assertions'; +import { WebSocketApi } from '@aws-cdk/aws-apigatewayv2'; +import { Stack } from '@aws-cdk/core'; +import { WebSocketMockIntegration } from '../../lib'; + + +describe('MockWebSocketIntegration', () => { + test('default', () => { + // GIVEN + const stack = new Stack(); + + // WHEN + new WebSocketApi(stack, 'Api', { + defaultRouteOptions: { integration: new WebSocketMockIntegration('DefaultIntegration') }, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { + IntegrationType: 'MOCK', + IntegrationUri: '', + }); + }); +}); diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts index 857ef57657736..58e9c9a60879a 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/http/integration.ts @@ -1,3 +1,4 @@ +import { IRole } from '@aws-cdk/aws-iam'; import { Resource } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { CfnIntegration } from '../apigatewayv2.generated'; @@ -23,15 +24,96 @@ export interface IHttpIntegration extends IIntegration { */ export enum HttpIntegrationType { /** - * Integration type is a Lambda proxy - * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + * Integration type is an HTTP proxy. + * + * For integrating the route or method request with an HTTP endpoint, with the + * client request passed through as-is. This is also referred to as HTTP proxy + * integration. For HTTP API private integrations, use an HTTP_PROXY integration. + * + * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-http.html */ - LAMBDA_PROXY = 'AWS_PROXY', + HTTP_PROXY = 'HTTP_PROXY', + /** - * Integration type is an HTTP proxy + * Integration type is an AWS proxy. + * + * For integrating the route or method request with a Lambda function or other + * AWS service action. This integration is also referred to as a Lambda proxy + * integration. + * + * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-aws-services.html * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html */ - HTTP_PROXY = 'HTTP_PROXY', + AWS_PROXY = 'AWS_PROXY', +} + +/** + * Supported integration subtypes + * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-aws-services-reference.html + */ +export enum HttpIntegrationSubtype { + /** + * EventBridge PutEvents integration + */ + EVENTBRIDGE_PUT_EVENTS = 'EventBridge-PutEvents', + /** + * SQS SendMessage integration + */ + SQS_SEND_MESSAGE = 'SQS-SendMessage', + /** + * SQS ReceiveMessage integration, + */ + SQS_RECEIVE_MESSAGE = 'SQS-ReceiveMessage', + /** + * SQS DeleteMessage integration, + */ + SQS_DELETE_MESSAGE = 'SQS-DeleteMessage', + /** + * SQS PurgeQueue integration + */ + SQS_PURGE_QUEUE = 'SQS-PurgeQueue', + /** + * AppConfig GetConfiguration integration + */ + APPCONFIG_GET_CONFIGURATION = 'AppConfig-GetConfiguration', + /** + * Kinesis PutRecord integration + */ + KINESIS_PUT_RECORD = 'Kinesis-PutRecord', + /** + * Step Functions StartExecution integration + */ + STEPFUNCTIONS_START_EXECUTION = 'StepFunctions-StartExecution', + /** + * Step Functions StartSyncExecution integration + */ + STEPFUNCTIONS_START_SYNC_EXECUTION = 'StepFunctions-StartSyncExecution', + /** + * Step Functions StopExecution integration + */ + STEPFUNCTIONS_STOP_EXECUTION = 'StepFunctions-StopExecution', +} + +/** + * Credentials used for AWS Service integrations. + */ +export abstract class IntegrationCredentials { + /** + * Use the specified role for integration requests + */ + public static fromRole(role: IRole): IntegrationCredentials { + return { credentialsArn: role.roleArn }; + } + + /** Use the calling user's identity to call the integration */ + public static useCallerIdentity(): IntegrationCredentials { + return { credentialsArn: 'arn:aws:iam::*:user/*' }; + } + + /** + * The ARN of the credentials + */ + public abstract readonly credentialsArn: string; } /** @@ -88,12 +170,23 @@ export interface HttpIntegrationProps { */ readonly integrationType: HttpIntegrationType; + /** + * Integration subtype. + * + * Used for AWS Service integrations, specifies the target of the integration. + * + * @default - none, required if no `integrationUri` is defined. + */ + readonly integrationSubtype?: HttpIntegrationSubtype; + /** * Integration URI. - * This will be the function ARN in the case of `HttpIntegrationType.LAMBDA_PROXY`, + * This will be the function ARN in the case of `HttpIntegrationType.AWS_PROXY`, * or HTTP URL in the case of `HttpIntegrationType.HTTP_PROXY`. + * + * @default - none, required if no `integrationSubtype` is defined. */ - readonly integrationUri: string; + readonly integrationUri?: string; /** * The HTTP method to use when calling the underlying HTTP proxy @@ -118,7 +211,7 @@ export interface HttpIntegrationProps { /** * The version of the payload format * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html - * @default - defaults to latest in the case of HttpIntegrationType.LAMBDA_PROXY`, irrelevant otherwise. + * @default - defaults to latest in the case of HttpIntegrationType.AWS_PROXY`, irrelevant otherwise. */ readonly payloadFormatVersion?: PayloadFormatVersion; @@ -135,6 +228,13 @@ export interface HttpIntegrationProps { * @default undefined requests are sent to the backend unmodified */ readonly parameterMapping?: ParameterMapping; + + /** + * The credentials with which to invoke the integration. + * + * @default - no credentials, use resource-based permissions on supported AWS services + */ + readonly credentials?: IntegrationCredentials; } /** @@ -148,15 +248,22 @@ export class HttpIntegration extends Resource implements IHttpIntegration { constructor(scope: Construct, id: string, props: HttpIntegrationProps) { super(scope, id); + + if (!props.integrationSubtype && !props.integrationUri) { + throw new Error('Either `integrationSubtype` or `integrationUri` must be specified.'); + } + const integ = new CfnIntegration(this, 'Resource', { apiId: props.httpApi.apiId, integrationType: props.integrationType, + integrationSubtype: props.integrationSubtype, integrationUri: props.integrationUri, integrationMethod: props.method, connectionId: props.connectionId, connectionType: props.connectionType, payloadFormatVersion: props.payloadFormatVersion?.version, requestParameters: props.parameterMapping?.mappings, + credentialsArn: props.credentials?.credentialsArn, }); if (props.secureServerName) { @@ -214,6 +321,7 @@ export abstract class HttpRouteIntegration { this.integration = new HttpIntegration(options.scope, this.id, { httpApi: options.route.httpApi, integrationType: config.type, + integrationSubtype: config.subtype, integrationUri: config.uri, method: config.method, connectionId: config.connectionId, @@ -221,6 +329,7 @@ export abstract class HttpRouteIntegration { payloadFormatVersion: config.payloadFormatVersion, secureServerName: config.secureServerName, parameterMapping: config.parameterMapping, + credentials: config.credentials, }); } return { integrationId: this.integration.integrationId }; @@ -241,10 +350,19 @@ export interface HttpRouteIntegrationConfig { */ readonly type: HttpIntegrationType; + /** + * Integration subtype. + * + * @default - none, required if no `integrationUri` is defined. + */ + readonly subtype?: HttpIntegrationSubtype; + /** * Integration URI + * + * @default - none, required if no `integrationSubtype` is defined. */ - readonly uri: string; + readonly uri?: string; /** * The HTTP method that must be used to invoke the underlying proxy. @@ -287,4 +405,11 @@ export interface HttpRouteIntegrationConfig { * @default undefined requests are sent to the backend unmodified */ readonly parameterMapping?: ParameterMapping; + + /** + * The credentials with which to invoke the integration. + * + * @default - no credentials, use resource-based permissions on supported AWS services + */ + readonly credentials?: IntegrationCredentials; } diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/parameter-mapping.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/parameter-mapping.ts index deb967d572de2..5b92a50d9ca61 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/parameter-mapping.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/parameter-mapping.ts @@ -71,6 +71,18 @@ export class MappingValue implements IMappingValue { * Represents a Parameter Mapping. */ export class ParameterMapping { + + /** + * Creates a mapping from an object. + */ + public static fromObject(obj: { [key: string]: MappingValue }): ParameterMapping { + const mapping = new ParameterMapping(); + for (const [k, m] of Object.entries(obj)) { + mapping.custom(k, m.value); + } + return mapping; + } + /** * Represents all created parameter mappings. */ @@ -142,4 +154,4 @@ export class ParameterMapping { this.mappings[key] = value; return this; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/integration.ts b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/integration.ts index b5366be83f2ba..028dfd07b7a97 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/integration.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/lib/websocket/integration.ts @@ -24,7 +24,11 @@ export enum WebSocketIntegrationType { /** * AWS Proxy Integration Type */ - AWS_PROXY = 'AWS_PROXY' + AWS_PROXY = 'AWS_PROXY', + /** + * Mock Integration Type + */ + MOCK = 'MOCK' } /** diff --git a/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts b/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts index 0f0d4d01fd1c5..7f64176446928 100644 --- a/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts +++ b/packages/@aws-cdk/aws-apigatewayv2/test/http/route.test.ts @@ -1,5 +1,5 @@ import { Template } from '@aws-cdk/assertions'; -import { AccountPrincipal, Role } from '@aws-cdk/aws-iam'; +import { AccountPrincipal, Role, ServicePrincipal } from '@aws-cdk/aws-iam'; import { Stack, App } from '@aws-cdk/core'; import { HttpApi, HttpAuthorizer, HttpAuthorizerType, HttpConnectionType, HttpIntegrationType, HttpMethod, HttpRoute, @@ -7,6 +7,8 @@ import { MappingValue, ParameterMapping, PayloadFormatVersion, + HttpIntegrationSubtype, + IntegrationCredentials, } from '../../lib'; describe('HttpRoute', () => { @@ -249,6 +251,56 @@ describe('HttpRoute', () => { Template.fromStack(stack).resourceCountIs('AWS::ApiGatewayV2::VpcLink', 0); }); + test('configures AWS service integration correctly', () => { + // GIVEN + const stack = new Stack(); + const httpApi = new HttpApi(stack, 'HttpApi'); + const role = new Role(stack, 'Role', { + assumedBy: new ServicePrincipal('apigateway.amazonaws.com'), + }); + + class SqsSendMessageIntegration extends HttpRouteIntegration { + public bind(): HttpRouteIntegrationConfig { + return { + method: HttpMethod.ANY, + payloadFormatVersion: PayloadFormatVersion.VERSION_1_0, + type: HttpIntegrationType.AWS_PROXY, + subtype: HttpIntegrationSubtype.SQS_SEND_MESSAGE, + credentials: IntegrationCredentials.fromRole(role), + parameterMapping: ParameterMapping.fromObject({ + QueueUrl: MappingValue.requestHeader('queueUrl'), + MessageBody: MappingValue.requestBody('message'), + }), + }; + } + } + + // WHEN + new HttpRoute(stack, 'HttpRoute', { + httpApi, + integration: new SqsSendMessageIntegration('SqsSendMessageIntegration'), + routeKey: HttpRouteKey.with('/sqs', HttpMethod.POST), + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApiGatewayV2::Integration', { + IntegrationType: 'AWS_PROXY', + IntegrationSubtype: 'SQS-SendMessage', + IntegrationMethod: 'ANY', + PayloadFormatVersion: '1.0', + CredentialsArn: { + 'Fn::GetAtt': [ + 'Role1ABCC5F0', + 'Arn', + ], + }, + RequestParameters: { + QueueUrl: '$request.header.queueUrl', + MessageBody: '$request.body.message', + }, + }); + }); + test('can create route with an authorizer attached', () => { const stack = new Stack(); const httpApi = new HttpApi(stack, 'HttpApi'); @@ -632,4 +684,4 @@ class SomeAuthorizerType implements IHttpRouteAuthorizer { authorizationType: this.authorizationType, }; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts b/packages/@aws-cdk/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts index c974a13d4ec8a..e0252b377ddc9 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/lib/target-tracking-scaling-policy.ts @@ -136,6 +136,11 @@ export class TargetTrackingScalingPolicy extends CoreConstruct { super(scope, id); + // replace dummy value in DYNAMODB_WRITE_CAPACITY_UTILIZATION due to a jsii bug (https://github.com/aws/jsii/issues/2782) + const predefinedMetric = props.predefinedMetric === PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION ? + PredefinedMetric.DYANMODB_WRITE_CAPACITY_UTILIZATION : + props.predefinedMetric; + const resource = new CfnScalingPolicy(this, 'Resource', { policyName: props.policyName || cdk.Names.uniqueId(this), policyType: 'TargetTrackingScaling', @@ -143,8 +148,8 @@ export class TargetTrackingScalingPolicy extends CoreConstruct { targetTrackingScalingPolicyConfiguration: { customizedMetricSpecification: renderCustomMetric(props.customMetric), disableScaleIn: props.disableScaleIn, - predefinedMetricSpecification: props.predefinedMetric !== undefined ? { - predefinedMetricType: props.predefinedMetric, + predefinedMetricSpecification: predefinedMetric !== undefined ? { + predefinedMetricType: predefinedMetric, resourceLabel: props.resourceLabel, } : undefined, scaleInCooldown: props.scaleInCooldown && props.scaleInCooldown.toSeconds(), @@ -183,9 +188,20 @@ export enum PredefinedMetric { * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html */ DYNAMODB_READ_CAPACITY_UTILIZATION = 'DynamoDBReadCapacityUtilization', + /** + * DYNAMODB_WRITE_CAPACITY_UTILIZATION + * + * Suffix `dummy` is necessary due to jsii bug (https://github.com/aws/jsii/issues/2782). + * Duplicate values will be dropped, so this suffix is added as a workaround. + * The value will be replaced when this enum is used. + * + * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html + */ + DYNAMODB_WRITE_CAPACITY_UTILIZATION = 'DynamoDBWriteCapacityUtilization-dummy', /** * DYANMODB_WRITE_CAPACITY_UTILIZATION * @see https://docs.aws.amazon.com/autoscaling/application/APIReference/API_PredefinedMetricSpecification.html + * @deprecated use `PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION` */ DYANMODB_WRITE_CAPACITY_UTILIZATION = 'DynamoDBWriteCapacityUtilization', /** diff --git a/packages/@aws-cdk/aws-applicationautoscaling/package.json b/packages/@aws-cdk/aws-applicationautoscaling/package.json index 8bd0c7c58bc3f..e9f6d2d248dc7 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/package.json +++ b/packages/@aws-cdk/aws-applicationautoscaling/package.json @@ -79,12 +79,12 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", - "fast-check": "^2.20.0", + "fast-check": "^2.21.0", "jest": "^27.4.7" }, "dependencies": { @@ -126,6 +126,7 @@ "docs-public-apis:@aws-cdk/aws-applicationautoscaling.StepScalingPolicyProps", "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.ECS_SERVICE_AVERAGE_CPU_UTILIZATION", "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.DYNAMODB_READ_CAPACITY_UTILIZATION", + "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION", "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.DYANMODB_WRITE_CAPACITY_UTILIZATION", "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.ALB_REQUEST_COUNT_PER_TARGET", "docs-public-apis:@aws-cdk/aws-applicationautoscaling.PredefinedMetric.RDS_READER_AVERAGE_CPU_UTILIZATION", diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts index 036fd608a5e6d..bb66486113531 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/scalable-target.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; @@ -20,7 +20,7 @@ describe('scalable target', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { ServiceNamespace: 'dynamodb', ScalableDimension: 'test:TestCount', ResourceId: 'test:this/test', @@ -43,7 +43,7 @@ describe('scalable target', () => { }); // THEN: no exception - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { ServiceNamespace: 'dynamodb', ScalableDimension: 'test:TestCount', ResourceId: 'test:this/test', @@ -65,7 +65,7 @@ describe('scalable target', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { ScheduledActions: [ { ScalableTargetAction: { @@ -104,11 +104,11 @@ describe('scalable target', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', Match.not({ Period: 60, - }); + })); - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'LessThanOrEqualToThreshold', EvaluationPeriods: 1, Metrics: [ @@ -203,7 +203,7 @@ describe('scalable target', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { ServiceNamespace: 'dynamodb', ScalableDimension: 'test:TestCount', ResourceId: 'test:this/test', diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/step-scaling-policy.test.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/step-scaling-policy.test.ts index ca1011881ec14..4e10b53ae9ce9 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/step-scaling-policy.test.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/step-scaling-policy.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { SynthUtils } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as cdk from '@aws-cdk/core'; import * as fc from 'fast-check'; @@ -132,7 +131,7 @@ describe('step scaling policy', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'StepScaling', ScalingTargetId: { Ref: 'Target3191CF44', @@ -169,14 +168,14 @@ describe('step scaling policy', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'StepScaling', StepScalingPolicyConfiguration: { AdjustmentType: 'ChangeInCapacity', MetricAggregationType: 'Average', }, }); - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 1, AlarmActions: [ @@ -209,14 +208,14 @@ describe('step scaling policy', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'StepScaling', StepScalingPolicyConfiguration: { AdjustmentType: 'ChangeInCapacity', MetricAggregationType: 'Maximum', }, }); - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 10, ExtendedStatistic: 'p99', @@ -247,14 +246,14 @@ describe('step scaling policy', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'StepScaling', StepScalingPolicyConfiguration: { AdjustmentType: 'ChangeInCapacity', MetricAggregationType: 'Maximum', }, }); - expect(stack).toHaveResource('AWS::CloudWatch::Alarm', { + Template.fromStack(stack).hasResourceProperties('AWS::CloudWatch::Alarm', { ComparisonOperator: 'GreaterThanOrEqualToThreshold', EvaluationPeriods: 10, DatapointsToAlarm: 6, @@ -297,7 +296,7 @@ function setupStepScaling(intervals: appscaling.ScalingInterval[]) { scalingSteps: intervals, }); - return new ScalingStackTemplate(SynthUtils.synthesize(stack).template); + return new ScalingStackTemplate(Template.fromStack(stack).toJSON()); } class ScalingStackTemplate { diff --git a/packages/@aws-cdk/aws-applicationautoscaling/test/target-tracking.test.ts b/packages/@aws-cdk/aws-applicationautoscaling/test/target-tracking.test.ts index 2ec9f8dd07a26..fb9f50e5722c7 100644 --- a/packages/@aws-cdk/aws-applicationautoscaling/test/target-tracking.test.ts +++ b/packages/@aws-cdk/aws-applicationautoscaling/test/target-tracking.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as cdk from '@aws-cdk/core'; import * as appscaling from '../lib'; @@ -17,7 +17,7 @@ describe('target tracking', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { PredefinedMetricSpecification: { PredefinedMetricType: 'EC2SpotFleetRequestAverageCPUUtilization' }, @@ -41,7 +41,7 @@ describe('target tracking', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { PredefinedMetricSpecification: { PredefinedMetricType: 'LambdaProvisionedConcurrencyUtilization' }, @@ -53,6 +53,26 @@ describe('target tracking', () => { }); + test('test setup target tracking on predefined metric for DYNAMODB_WRITE_CAPACITY_UTILIZATION', () => { + // GIVEN + const stack = new cdk.Stack(); + const target = createScalableTarget(stack); + + // WHEN + target.scaleToTrackMetric('Tracking', { + predefinedMetric: appscaling.PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION, + targetValue: 0.9, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { + TargetTrackingScalingPolicyConfiguration: { + PredefinedMetricSpecification: { PredefinedMetricType: 'DynamoDBWriteCapacityUtilization' }, + TargetValue: 0.9, + }, + }); + }); + test('test setup target tracking on custom metric', () => { // GIVEN const stack = new cdk.Stack(); @@ -65,7 +85,7 @@ describe('target tracking', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { CustomizedMetricSpecification: { diff --git a/packages/@aws-cdk/aws-apprunner/test/service.test.ts b/packages/@aws-cdk/aws-apprunner/test/service.test.ts index 412ff09cd14e9..2d5285d06f7fa 100644 --- a/packages/@aws-cdk/aws-apprunner/test/service.test.ts +++ b/packages/@aws-cdk/aws-apprunner/test/service.test.ts @@ -1,5 +1,4 @@ import * as path from 'path'; -import '@aws-cdk/assert-internal/jest'; import { Template } from '@aws-cdk/assertions'; import * as ecr from '@aws-cdk/aws-ecr'; import * as ecr_assets from '@aws-cdk/aws-ecr-assets'; diff --git a/packages/@aws-cdk/aws-autoscaling-common/package.json b/packages/@aws-cdk/aws-autoscaling-common/package.json index 6118d3a13aa8a..6a0a7fa6efafd 100644 --- a/packages/@aws-cdk/aws-autoscaling-common/package.json +++ b/packages/@aws-cdk/aws-autoscaling-common/package.json @@ -64,12 +64,11 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", - "fast-check": "^2.20.0", + "fast-check": "^2.21.0", "jest": "^27.4.7" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-autoscaling-common/test/intervals.test.ts b/packages/@aws-cdk/aws-autoscaling-common/test/intervals.test.ts index 0b0b9b996a1bb..e36923299003f 100644 --- a/packages/@aws-cdk/aws-autoscaling-common/test/intervals.test.ts +++ b/packages/@aws-cdk/aws-autoscaling-common/test/intervals.test.ts @@ -14,8 +14,6 @@ describe('intervals', () => { { lower: 80, upper: 90, change: +1 }, { lower: 90, upper: Infinity, change: +2 }, ]); - - }); test('test interval completion', () => { @@ -37,8 +35,6 @@ describe('intervals', () => { { lower: 65, upper: 85, change: +3 }, { lower: 85, upper: Infinity, change: undefined }, ]); - - }); test('bounds propagation fails if middle boundary missing', () => { @@ -48,8 +44,6 @@ describe('intervals', () => { { upper: 20, change: -1 }, ], false); }).toThrow(); - - }); test('lower alarm index is lower than higher alarm index', () => { @@ -63,8 +57,6 @@ describe('intervals', () => { || alarms.lowerAlarmIntervalIndex < alarms.upperAlarmIntervalIndex); }, )); - - }); test('never pick undefined intervals for relative alarms', () => { @@ -77,8 +69,6 @@ describe('intervals', () => { && (alarms.upperAlarmIntervalIndex === undefined || intervals[alarms.upperAlarmIntervalIndex].change !== undefined); }, )); - - }); test('pick intervals on either side of the undefined interval, if present', () => { @@ -93,8 +83,6 @@ describe('intervals', () => { return (alarms.lowerAlarmIntervalIndex === i - 1 && alarms.upperAlarmIntervalIndex === i + 1); }, )); - - }); test('no picking upper bound infinity for lower alarm', () => { @@ -107,8 +95,6 @@ describe('intervals', () => { return intervals[alarms.lowerAlarmIntervalIndex!].upper !== Infinity; }, )); - - }); test('no picking lower bound 0 for upper alarm', () => { @@ -121,8 +107,6 @@ describe('intervals', () => { return intervals[alarms.upperAlarmIntervalIndex!].lower !== 0; }, )); - - }); }); diff --git a/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json b/packages/@aws-cdk/aws-certificatemanager/lambda-packages/dns_validated_certificate_handler/package.json index d827908659d85..db0b2433d6583 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 @@ -43,7 +43,7 @@ "jest": "^27.4.7", "lambda-tester": "^3.6.0", "sinon": "^9.2.4", - "nock": "^13.2.1", + "nock": "^13.2.2", "ts-jest": "^27.1.2" } } diff --git a/packages/@aws-cdk/aws-cloudformation/package.json b/packages/@aws-cdk/aws-cloudformation/package.json index c00a412462faa..5a7014994d6c5 100644 --- a/packages/@aws-cdk/aws-cloudformation/package.json +++ b/packages/@aws-cdk/aws-cloudformation/package.json @@ -69,7 +69,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-s3-assets": "0.0.0", "@aws-cdk/aws-sns-subscriptions": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts b/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts index 0354c7e9e4fa8..1e814b754eece 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/deps.test.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; -import { ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { testDeprecated, describeDeprecated } from '@aws-cdk/cdk-build-tools'; import { App, CfnResource, Stack } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; @@ -39,8 +38,8 @@ describe('resource dependencies', () => { // THEN: the dependency needs to transfer from the resource within the // nested stack to the nested stack resource itself so the nested stack // will only be deployed the dependent resource - expect(parent).toHaveResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInParent'] }, ResourcePart.CompleteDefinition); - expect(nested).toMatchTemplate({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource + Template.fromStack(parent).hasResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInParent'] }); + Template.fromStack(nested).templateMatches({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource })); // eslint-disable-next-line jest/valid-describe @@ -57,8 +56,8 @@ describe('resource dependencies', () => { // THEN: the dependency needs to transfer from the resource within the // nested stack to the *parent* nested stack - expect(grantparent).toHaveResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInGrandparent'] }, ResourcePart.CompleteDefinition); - expect(nested).toMatchTemplate({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource + Template.fromStack(grantparent).hasResource('AWS::CloudFormation::Stack', { DependsOn: ['ResourceInGrandparent'] }); + Template.fromStack(nested).templateMatches({ Resources: { ResourceInNested: { Type: 'NESTED' } } }); // no DependsOn for the actual resource })); // eslint-disable-next-line jest/valid-describe @@ -73,9 +72,9 @@ describe('resource dependencies', () => { addDep(resourceInParent, resourceInNested); // THEN: resource in parent needs to depend on the nested stack - expect(parent).toHaveResource('PARENT', { + Template.fromStack(parent).hasResource('PARENT', { DependsOn: [parent.resolve(nested.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); })); // eslint-disable-next-line jest/valid-describe @@ -91,9 +90,9 @@ describe('resource dependencies', () => { addDep(resourceInGrandparent, resourceInNested); // THEN: resource in grantparent needs to depend on the top-level nested stack - expect(grandparent).toHaveResource('GRANDPARENT', { + Template.fromStack(grandparent).hasResource('GRANDPARENT', { DependsOn: [grandparent.resolve(parent.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); })); // eslint-disable-next-line jest/valid-describe @@ -154,13 +153,13 @@ describe('resource dependencies', () => { addDep(resourceInNested1, resourceInNested2); // THEN: dependency transfered to nested stack resources - expect(stack).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(stack).hasResource('AWS::CloudFormation::Stack', { DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); - expect(stack).not.toHaveResource('AWS::CloudFormation::Stack', { + expect(Template.fromStack(stack).findResources('AWS::CloudFormation::Stack', { DependsOn: [stack.resolve(nested1.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + })).toEqual({}); })); }); @@ -226,9 +225,9 @@ describe('stack dependencies', () => { nested1.addDependency(nested2); // THEN - expect(stack).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(stack).hasResource('AWS::CloudFormation::Stack', { DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); }); testDeprecated('nested stack depends on a deeply nested stack', () => { @@ -242,9 +241,9 @@ describe('stack dependencies', () => { nested1.addDependency(nested21); // THEN: transfered to a resource dep between the resources in the common stack - expect(stack).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(stack).hasResource('AWS::CloudFormation::Stack', { DependsOn: [stack.resolve(nested2.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); }); testDeprecated('deeply nested stack depends on a parent nested stack', () => { @@ -258,9 +257,9 @@ describe('stack dependencies', () => { nested21.addDependency(nested1); // THEN: transfered to a resource dep between the resources in the common stack - expect(stack).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(stack).hasResource('AWS::CloudFormation::Stack', { DependsOn: [stack.resolve(nested1.nestedStackResource!.logicalId)], - }, ResourcePart.CompleteDefinition); + }); }); testDeprecated('top-level stack depends on a nested stack within a sibling', () => { diff --git a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts index 07a43586971bd..a625012eba58a 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/nested-stack.test.ts @@ -1,7 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; -import { SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as s3_assets from '@aws-cdk/aws-s3-assets'; import * as sns from '@aws-cdk/aws-sns'; import { describeDeprecated } from '@aws-cdk/cdk-build-tools'; @@ -122,7 +121,7 @@ describeDeprecated('NestedStack', () => { }); // the parent template includes the parameters and the nested stack resource which points to the s3 url - expect(parent).toMatchTemplate({ + Template.fromStack(parent).templateMatches({ Resources: { nestedstackNestedStacknestedstackNestedStackResource71CDD241: { Type: 'AWS::CloudFormation::Stack', @@ -276,7 +275,7 @@ describeDeprecated('NestedStack', () => { app.synth(); // nested template should use a parameter to reference the resource from the parent stack - expect(nested).toMatchTemplate({ + Template.fromStack(nested).templateMatches({ Resources: { resource: @@ -303,7 +302,7 @@ describeDeprecated('NestedStack', () => { }); // parent template should pass in the value through the parameter - expect(parentStack).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(parentStack).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetoparentparentresourceD56EA8F7Ref: { Ref: 'parentresource', @@ -347,7 +346,7 @@ describeDeprecated('NestedStack', () => { app.synth(); // nested template should use a parameter to reference the resource from the parent stack - expect(nested).toMatchTemplate({ + Template.fromStack(nested).templateMatches({ Resources: { resource: { Type: 'AWS::Child::Resource' }, }, @@ -357,7 +356,7 @@ describeDeprecated('NestedStack', () => { }); // parent template should pass in the value through the parameter - expect(parentStack).toHaveResource('AWS::Parent::Resource', { + Template.fromStack(parentStack).hasResourceProperties('AWS::Parent::Resource', { RefToResourceInNestedStack: { 'Fn::GetAtt': [ 'nestedNestedStacknestedNestedStackResource3DD143BF', @@ -387,7 +386,7 @@ describeDeprecated('NestedStack', () => { const assembly = app.synth(); // producing stack should have an export - expect(stack2).toMatchTemplate({ + Template.fromStack(stack2).templateMatches({ Resources: { ResourceInStack2: { Type: 'MyResource' }, }, @@ -400,7 +399,7 @@ describeDeprecated('NestedStack', () => { }); // nested stack uses Fn::ImportValue like normal - expect(nestedUnderStack1).toMatchTemplate({ + Template.fromStack(nestedUnderStack1).templateMatches({ Resources: { ResourceInNestedStack1: { Type: 'Nested::Resource', @@ -464,7 +463,7 @@ describeDeprecated('NestedStack', () => { const assembly = app.synth(); // nested stack should output this value as if it was referenced by the parent (without the export) - expect(nestedUnderStack1).toMatchTemplate({ + Template.fromStack(nestedUnderStack1).templateMatches({ Resources: { ResourceInNestedStack: { Type: 'MyResource', @@ -491,7 +490,7 @@ describeDeprecated('NestedStack', () => { }); // consuming stack should use ImportValue to import the value from the parent stack - expect(stack2).toMatchTemplate({ + Template.fromStack(stack2).templateMatches({ Resources: { ResourceInStack2: { Type: 'JustResource', @@ -532,7 +531,7 @@ describeDeprecated('NestedStack', () => { app.synth(); // producing nested stack - expect(nested1).toMatchTemplate({ + Template.fromStack(nested1).templateMatches({ Resources: { Resource1: { Type: 'Resource1', @@ -548,7 +547,7 @@ describeDeprecated('NestedStack', () => { }); // consuming nested stack - expect(nested2).toMatchTemplate({ + Template.fromStack(nested2).templateMatches({ Resources: { Resource2: { Type: 'Resource2', @@ -567,7 +566,7 @@ describeDeprecated('NestedStack', () => { }); // parent - expect(parent).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(parent).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetoParentNested1NestedStackNested1NestedStackResource9C05342COutputsParentNested1Resource15F3F0657Ref: { 'Fn::GetAtt': [ @@ -591,7 +590,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(nested).toHaveResource('Nested::Resource', { + Template.fromStack(nested).hasResourceProperties('Nested::Resource', { MyStackId: { Ref: 'AWS::StackId' }, }); }); @@ -608,7 +607,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(parent).toHaveResource('Parent::Resource', { + Template.fromStack(parent).hasResourceProperties('Parent::Resource', { NestedStackId: { Ref: 'NestedStackNestedStackNestedStackNestedStackResourceB70834FD' }, }); }); @@ -625,7 +624,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(nested).toHaveResource('Nested::Resource', { + Template.fromStack(nested).hasResourceProperties('Nested::Resource', { MyStackName: { Ref: 'AWS::StackName' }, }); }); @@ -642,7 +641,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(parent).toHaveResource('Parent::Resource', { + Template.fromStack(parent).hasResourceProperties('Parent::Resource', { NestedStackName: { 'Fn::Select': [ 1, @@ -689,7 +688,7 @@ describeDeprecated('NestedStack', () => { const assembly = app.synth(); // nested2 is a "leaf", so it's just the resource - expect(nested2).toMatchTemplate({ + Template.fromStack(nested2).templateMatches({ Resources: { Resource2: { Type: 'Resource::2' }, }, @@ -701,8 +700,9 @@ describeDeprecated('NestedStack', () => { const hashSuffix = 'E28F0693'; // nested1 wires the nested2 template through parameters, so we expect those - expect(nested1).toHaveResource('Resource::1'); - const nested2Template = SynthUtils.toCloudFormation(nested1); + const nested1Template = Template.fromStack(nested1); + nested1Template.resourceCountIs('Resource::1', 1); + const nested2Template = nested1Template.toJSON(); expect(nested2Template.Parameters).toEqual({ referencetostackAssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3BucketE8768F5CRef: { Type: 'String' }, referencetostackAssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3VersionKey49DD83A2Ref: { Type: 'String' }, @@ -710,7 +710,7 @@ describeDeprecated('NestedStack', () => { // parent stack should have two sets of parameters. one for the first nested stack and the second // for the second nested stack, passed in as parameters to the first - const template = SynthUtils.toCloudFormation(parent); + const template = Template.fromStack(parent).toJSON(); expect(template.Parameters).toEqual({ AssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3BucketDE3B88D6: { Type: 'String', Description: 'S3 bucket for asset "8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235c"' }, AssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3VersionKey3A62EFEA: { Type: 'String', Description: 'S3 key for asset version "8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235c"' }, @@ -721,7 +721,7 @@ describeDeprecated('NestedStack', () => { }); // proxy asset params to nested stack - expect(parent).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(parent).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetostackAssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3BucketE8768F5CRef: { Ref: 'AssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3BucketDE3B88D6' }, referencetostackAssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3VersionKey49DD83A2Ref: { Ref: 'AssetParameters8169c6f8aaeaf5e2e8620f5f895ffe2099202ccb4b6889df48fe0967a894235cS3VersionKey3A62EFEA' }, @@ -780,7 +780,7 @@ describeDeprecated('NestedStack', () => { // THEN const assembly = app.synth(); - const template = SynthUtils.toCloudFormation(parent); + const template = Template.fromStack(parent).toJSON(); // two sets of asset parameters: one for the nested stack itself and one as a proxy for the asset within the stack expect(template.Parameters).toEqual({ @@ -793,7 +793,7 @@ describeDeprecated('NestedStack', () => { }); // asset proxy parameters are passed to the nested stack - expect(parent).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(parent).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetoParentStackAssetParametersdb01ee2eb7adc7915e364dc410d861e569543f9be3761d535a68d5c2cc181281S3Bucket82C55B96Ref: { Ref: 'AssetParametersdb01ee2eb7adc7915e364dc410d861e569543f9be3761d535a68d5c2cc181281S3BucketC188F637' }, referencetoParentStackAssetParametersdb01ee2eb7adc7915e364dc410d861e569543f9be3761d535a68d5c2cc181281S3VersionKeyA43C3CC6Ref: { Ref: 'AssetParametersdb01ee2eb7adc7915e364dc410d861e569543f9be3761d535a68d5c2cc181281S3VersionKeyC7F4DBF2' }, @@ -887,7 +887,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(nested).toMatchTemplate({ + Template.fromStack(nested).templateMatches({ Resources: { resourceinnested: { Type: 'CONSUMED', @@ -905,7 +905,7 @@ describeDeprecated('NestedStack', () => { }, }); - expect(parent).toHaveResource('CONSUMER', { + Template.fromStack(parent).hasResourceProperties('CONSUMER', { ConsumedAttribute: { 'Fn::GetAtt': [ 'nestedNestedStacknestedNestedStackResource3DD143BF', @@ -984,7 +984,7 @@ describeDeprecated('NestedStack', () => { }); // THEN - expect(top).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(top).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetostackAssetParameters842982bd421cce9742ba27151ef12ed699d44d22801f41e8029f63f2358a3f2fS3Bucket5DA5D2E7Ref: { Ref: 'AssetParameters842982bd421cce9742ba27151ef12ed699d44d22801f41e8029f63f2358a3f2fS3BucketDD4D96B5', @@ -998,7 +998,7 @@ describeDeprecated('NestedStack', () => { }, }); - expect(nested1).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(nested1).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { referencetostacktoplevelBB16BF13Ref: { Ref: 'referencetostacktoplevelBB16BF13Ref', @@ -1006,7 +1006,7 @@ describeDeprecated('NestedStack', () => { }, }); - expect(nested2).toMatchTemplate({ + Template.fromStack(nested2).templateMatches({ Resources: { refToTopLevel: { Type: 'BottomLevel', @@ -1048,7 +1048,7 @@ describeDeprecated('NestedStack', () => { const paramName = 'referencetoGrandparentResourceInGrandparent010E997ARef'; // child (bottom) references through a parameter. - expect(bottom).toMatchTemplate({ + Template.fromStack(bottom).templateMatches({ Resources: { ResourceInChild: { Type: 'ResourceInChild', @@ -1063,14 +1063,14 @@ describeDeprecated('NestedStack', () => { }); // the parent (middle) sets the value of this parameter to be a reference to another parameter - expect(middle).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(middle).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { [paramName]: { Ref: paramName }, }, }); // grandparent (top) assigns the actual value to the parameter - expect(top).toHaveResource('AWS::CloudFormation::Stack', { + Template.fromStack(top).hasResourceProperties('AWS::CloudFormation::Stack', { Parameters: { [paramName]: { Ref: 'ResourceInGrandparent' }, diff --git a/packages/@aws-cdk/aws-cloudformation/test/resource.test.ts b/packages/@aws-cdk/aws-cloudformation/test/resource.test.ts index c6cefdc714675..e2f6eae16f3b3 100644 --- a/packages/@aws-cdk/aws-cloudformation/test/resource.test.ts +++ b/packages/@aws-cdk/aws-cloudformation/test/resource.test.ts @@ -1,5 +1,4 @@ -import { ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; import * as sns from '@aws-cdk/aws-sns'; import { describeDeprecated, testDeprecated } from '@aws-cdk/cdk-build-tools'; @@ -23,7 +22,7 @@ describeDeprecated('custom resources honor removalPolicy', () => { new TestCustomResource(stack, 'Custom'); // THEN - expect(stack).toHaveResource('AWS::CloudFormation::CustomResource', {}, ResourcePart.CompleteDefinition); + Template.fromStack(stack).hasResource('AWS::CloudFormation::CustomResource', {}); expect(app.synth().tryGetArtifact(stack.stackName)!.findMetadataByType('aws:cdk:protected').length).toEqual(0); }); @@ -36,7 +35,7 @@ describeDeprecated('custom resources honor removalPolicy', () => { new TestCustomResource(stack, 'Custom', { removalPolicy: cdk.RemovalPolicy.DESTROY }); // THEN - expect(stack).toHaveResource('AWS::CloudFormation::CustomResource', {}, ResourcePart.CompleteDefinition); + Template.fromStack(stack).hasResource('AWS::CloudFormation::CustomResource', {}); expect(app.synth().tryGetArtifact(stack.stackName)!.findMetadataByType('aws:cdk:protected').length).toEqual(0); }); @@ -49,10 +48,10 @@ describeDeprecated('custom resources honor removalPolicy', () => { new TestCustomResource(stack, 'Custom', { removalPolicy: cdk.RemovalPolicy.RETAIN }); // THEN - expect(stack).toHaveResource('AWS::CloudFormation::CustomResource', { + Template.fromStack(stack).hasResource('AWS::CloudFormation::CustomResource', { DeletionPolicy: 'Retain', UpdateReplacePolicy: 'Retain', - }, ResourcePart.CompleteDefinition); + }); }); }); @@ -66,7 +65,7 @@ testDeprecated('custom resource is added twice, lambda is added once', () => { new TestCustomResource(stack, 'Custom2'); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'SingletonLambdaTestCustomResourceProviderServiceRole81FEAB5C': { 'Type': 'AWS::IAM::Role', @@ -149,7 +148,7 @@ testDeprecated('custom resources can specify a resource type that starts with Cu resourceType: 'Custom::MyCustomResourceType', provider: CustomResourceProvider.fromTopic(new sns.Topic(stack, 'Provider')), }); - expect(stack).toHaveResource('Custom::MyCustomResourceType'); + Template.fromStack(stack).hasResourceProperties('Custom::MyCustomResourceType', {}); }); describeDeprecated('fails if custom resource type is invalid', () => { diff --git a/packages/@aws-cdk/aws-codeguruprofiler/package.json b/packages/@aws-cdk/aws-codeguruprofiler/package.json index fd38f19937410..92aaf5b19dbba 100644 --- a/packages/@aws-cdk/aws-codeguruprofiler/package.json +++ b/packages/@aws-cdk/aws-codeguruprofiler/package.json @@ -74,7 +74,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codeguruprofiler/test/profiling-group.test.ts b/packages/@aws-cdk/aws-codeguruprofiler/test/profiling-group.test.ts index 00212902bbec6..94f54c65945c4 100644 --- a/packages/@aws-cdk/aws-codeguruprofiler/test/profiling-group.test.ts +++ b/packages/@aws-cdk/aws-codeguruprofiler/test/profiling-group.test.ts @@ -1,4 +1,4 @@ -import { expect, haveResourceLike } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import { AccountRootPrincipal, Role } from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; import { ProfilingGroup, ComputePlatform } from '../lib'; @@ -6,7 +6,6 @@ import { ProfilingGroup, ComputePlatform } from '../lib'; /* eslint-disable quote-props */ describe('profiling group', () => { - test('attach read permission to Profiling group via fromProfilingGroupArn', () => { const stack = new Stack(); // dummy role to test out read permissions on ProfilingGroup @@ -17,7 +16,7 @@ describe('profiling group', () => { const profilingGroup = ProfilingGroup.fromProfilingGroupArn(stack, 'MyProfilingGroup', 'arn:aws:codeguru-profiler:us-east-1:1234567890:profilingGroup/MyAwesomeProfilingGroup'); profilingGroup.grantRead(readAppRole); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'ReadAppRole52FE6317': { 'Type': 'AWS::IAM::Role', @@ -89,7 +88,7 @@ describe('profiling group', () => { const profilingGroup = ProfilingGroup.fromProfilingGroupName(stack, 'MyProfilingGroup', 'MyAwesomeProfilingGroup'); profilingGroup.grantPublish(publishAppRole); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'PublishAppRole9FEBD682': { 'Type': 'AWS::IAM::Role', @@ -176,7 +175,7 @@ describe('profiling group', () => { profilingGroupName: 'MyAwesomeProfilingGroup', }); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyProfilingGroup829F0507': { 'Type': 'AWS::CodeGuruProfiler::ProfilingGroup', @@ -195,9 +194,9 @@ describe('profiling group', () => { computePlatform: ComputePlatform.AWS_LAMBDA, }); - expect(stack).to(haveResourceLike('AWS::CodeGuruProfiler::ProfilingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeGuruProfiler::ProfilingGroup', { 'ComputePlatform': 'AWSLambda', - })); + }); }); test('default profiling group without name', () => { @@ -205,7 +204,7 @@ describe('profiling group', () => { new ProfilingGroup(stack, 'MyProfilingGroup', { }); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyProfilingGroup829F0507': { 'Type': 'AWS::CodeGuruProfiler::ProfilingGroup', @@ -222,7 +221,7 @@ describe('profiling group', () => { new ProfilingGroup(stack, 'MyProfilingGroupWithAReallyLongProfilingGroupNameThatExceedsTheLimitOfProfilingGroupNameSize_InOrderToDoSoTheNameMustBeGreaterThanTwoHundredAndFiftyFiveCharacters_InSuchCasesWePickUpTheFirstOneTwentyCharactersFromTheBeginningAndTheEndAndConcatenateThemToGetTheIdentifier', { }); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyProfilingGroupWithAReallyLongProfilingGroupNameThatExceedsTheLimitOfProfilingGroupNameSizeInOrderToDoSoTheNameMustBeGreaterThanTwoHundredAndFiftyFiveCharactersInSuchCasesWePickUpTheFirstOneTwentyCharactersFromTheBeginningAndTheEndAndConca4B39908C': { 'Type': 'AWS::CodeGuruProfiler::ProfilingGroup', @@ -245,7 +244,7 @@ describe('profiling group', () => { profilingGroup.grantPublish(publishAppRole); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyProfilingGroup829F0507': { 'Type': 'AWS::CodeGuruProfiler::ProfilingGroup', @@ -329,7 +328,7 @@ describe('profiling group', () => { profilingGroup.grantRead(readAppRole); - expect(stack).toMatch({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyProfilingGroup829F0507': { 'Type': 'AWS::CodeGuruProfiler::ProfilingGroup', @@ -401,5 +400,4 @@ describe('profiling group', () => { }, }); }); - }); diff --git a/packages/@aws-cdk/aws-codestarnotifications/package.json b/packages/@aws-cdk/aws-codestarnotifications/package.json index e5b0e08f7ac76..251b0b0fa69f7 100644 --- a/packages/@aws-cdk/aws-codestarnotifications/package.json +++ b/packages/@aws-cdk/aws-codestarnotifications/package.json @@ -74,7 +74,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codestarnotifications/test/notification-rule.test.ts b/packages/@aws-cdk/aws-codestarnotifications/test/notification-rule.test.ts index 332e808ca3176..6670135d5a416 100644 --- a/packages/@aws-cdk/aws-codestarnotifications/test/notification-rule.test.ts +++ b/packages/@aws-cdk/aws-codestarnotifications/test/notification-rule.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as notifications from '../lib'; import { @@ -24,7 +24,7 @@ describe('NotificationRule', () => { events: ['codebuild-project-build-state-succeeded'], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], }); @@ -41,7 +41,7 @@ describe('NotificationRule', () => { ], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Resource: repository.repositoryArn, EventTypeIds: [ 'codecommit-repository-pull-request-created', @@ -65,7 +65,7 @@ describe('NotificationRule', () => { targets: [slack], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'MyNotificationRule', DetailType: 'FULL', EventTypeIds: [ @@ -90,7 +90,7 @@ describe('NotificationRule', () => { events: ['codebuild-project-build-state-succeeded'], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'MyNotificationRuleGeneratedFromId', Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], @@ -105,7 +105,7 @@ describe('NotificationRule', () => { events: ['codebuild-project-build-state-succeeded'], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'ificationRuleGeneratedFromIdIsToooooooooooooooooooooooooooooLong', Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], @@ -121,7 +121,7 @@ describe('NotificationRule', () => { events: ['codebuild-project-build-state-succeeded'], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'MyNotificationRule', Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], @@ -138,7 +138,7 @@ describe('NotificationRule', () => { enabled: false, }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'MyNotificationRule', Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], @@ -155,7 +155,7 @@ describe('NotificationRule', () => { enabled: true, }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Name: 'MyNotificationRule', Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], @@ -177,7 +177,7 @@ describe('NotificationRule', () => { expect(rule.addTarget(topic)).toEqual(true); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Resource: project.projectArn, EventTypeIds: ['codebuild-project-build-state-succeeded'], Targets: [ @@ -206,7 +206,7 @@ describe('NotificationRule', () => { ], }); - expect(stack).toHaveResourceLike('AWS::CodeStarNotifications::NotificationRule', { + Template.fromStack(stack).hasResourceProperties('AWS::CodeStarNotifications::NotificationRule', { Resource: pipeline.pipelineArn, EventTypeIds: [ 'codepipeline-pipeline-pipeline-execution-succeeded', diff --git a/packages/@aws-cdk/aws-cognito-identitypool/.eslintrc.js b/packages/@aws-cdk/aws-cognito-identitypool/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-cognito-identitypool/.gitignore b/packages/@aws-cdk/aws-cognito-identitypool/.gitignore new file mode 100644 index 0000000000000..d8a8561d50885 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +nyc.config.js +.LAST_PACKAGE +*.snk +!.eslintrc.js +!jest.config.js + +junit.xml \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/.npmignore b/packages/@aws-cdk/aws-cognito-identitypool/.npmignore new file mode 100644 index 0000000000000..aaabf1df59065 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/.npmignore @@ -0,0 +1,28 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/LICENSE b/packages/@aws-cdk/aws-cognito-identitypool/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-cognito-identitypool/NOTICE b/packages/@aws-cdk/aws-cognito-identitypool/NOTICE new file mode 100644 index 0000000000000..1e8442b37b61d --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/README.md b/packages/@aws-cdk/aws-cognito-identitypool/README.md new file mode 100644 index 0000000000000..fb1fc6ef0c0df --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/README.md @@ -0,0 +1,356 @@ +# Amazon Cognito Identity Pool Construct Library + +> **Identity Pools are in a separate module while the API is being stabilized. Once we stabilize the module, they will** +**be included into the stable [aws-cognito](../aws-cognito) library. Please provide feedback on this experience by** +**creating an [issue here](https://github.com/aws/aws-cdk/issues/new/choose)** + + + +--- + +![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge) + +> The APIs of higher level constructs in this module are experimental and under active development. +> They are subject to non-backward compatible changes or removal in any future version. These are +> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be +> announced in the release notes. This means that while you may use them, you may need to update +> your source code when upgrading to a newer version of this package. + +--- + + + +[Amazon Cognito Identity Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html) enable you to grant your users access to other AWS services. + +Identity Pools are one of the two main components of [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html), which provides authentication, authorization, and +user management for your web and mobile apps. Your users can sign in directly with a user name and password, or through +a third party such as Facebook, Amazon, Google or Apple. + +The other main component in Amazon Cognito is [user pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html). User Pools are user directories that provide sign-up and +sign-in options for your app users. + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +## Table of Contents + +- [Identity Pools](#identity-pools) + - [Authenticated and Unauthenticated Identities](#authenticated-and-unauthenticated-identities) + - [Authentication Providers](#authentication-providers) + - [User Pool Authentication Provider](#user-pool-authentication-provider) + - [Server Side Token Check](#server-side-token-check) + - [Associating an External Provider Directly](#associating-an-external-provider-directly) + - [OpenIdConnect and Saml](#openid-connect-and-saml) + - [Custom Providers](#custom-providers) + - [Role Mapping](#role-mapping) + - [Provider Urls](#provider-urls) + - [Authentication Flow](#authentication-flow) + - [Cognito Sync](#cognito-sync) + - [Importing Identity Pools](#importing-identity-pools) + +## Identity Pools + +Identity pools provide temporary AWS credentials for users who are guests (unauthenticated) and for users who have been +authenticated and received a token. An identity pool is a store of user identity data specific to an account. + +Identity pools can be used in conjunction with Cognito User Pools or by accessing external federated identity providers +directly. Learn more at [Amazon Cognito Identity Pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html). + +### Authenticated and Unauthenticated Identities + +Identity pools define two types of identities: authenticated(`user`) and unauthenticated (`guest`). Every identity in +an identity pool is either authenticated or unauthenticated. Each identity pool has a default role for authenticated +identities, and a default role for unauthenticated identities. Absent other overriding rules (see below), these are the +roles that will be assumed by the corresponding users in the authentication process. + +A basic Identity Pool with minimal configuration has no required props, with default authenticated (user) and +unauthenticated (guest) roles applied to the identity pool: + +```ts +new cognito.IdentityPool(this, 'myIdentityPool'); +``` + +By default, both the authenticated and unauthenticated roles will have no permissions attached. Grant permissions +to roles using the public `authenticatedRole` and `unauthenticatedRole` properties: + +```ts +const identityPool = new cognito.IdentityPool(this, 'myIdentityPool'); +const table = new dynamodb.Table(this, 'MyTable'); + +// Grant permissions to authenticated users +table.grantReadWriteData(identityPool.authenticatedRole); +// Grant permissions to unauthenticated guest users +table.grantRead(identityPool.unauthenticatedRole); + +//Or add policy statements straight to the role +identityPool.authenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['dynamodb:*'], + resources: ['*'] +})); +``` + +The default roles can also be supplied in `IdentityPoolProps`: + +```ts +const stack = new Stack(); +const authenticatedRole = new Role(stack, 'authRole', { + assumedBy: new ServicePrincipal('service.amazonaws.com'), +}); +const unauthenticatedRole = new Role(stack, 'unauthRole', { + assumedBy: new ServicePrincipal('service.amazonaws.com'), +}); +const identityPool = new IdentityPool(stack, 'TestIdentityPoolActions', { + authenticatedRole, unauthenticatedRole +}); +``` + +### Authentication Providers + +Authenticated identities belong to users who are authenticated by a public login provider (Amazon Cognito user pools, +Login with Amazon, Sign in with Apple, Facebook, Google, SAML, or any OpenID Connect Providers) or a developer provider +(your own backend authentication process). + +[Authentication providers](https://docs.aws.amazon.com/cognito/latest/developerguide/external-identity-providers.html) can be associated with an Identity Pool by first associating them with a Cognito User Pool or by +associating the provider directly with the identity pool. + +#### User Pool Authentication Provider + +In order to attach a user pool to an identity pool as an authentication provider, the identity pool needs properties +from both the user pool and the user pool client. For this reason identity pools use a `UserPoolAuthenticationProvider` +to gather the necessary properties from the user pool constructs. + +```ts +const userPool = new cognito.UserPool(this, 'Pool'); + +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + authenticationProviders: { + userPools: [new UserPoolAuthenticationProvider({ userPool })], + }, +}); +``` + +User pools can also be associated with an identity pool after instantiation. The Identity Pool's `addUserPoolAuthentication` method +returns the User Pool Client that has been created: + +```ts +const userPool = new cognito.UserPool(this, 'Pool'); +const userPoolClient = identityPool.addUserPoolAuthentication({ + userPools: [new UserPoolAuthenticationProvider({ userPool })]; +}); +``` + +#### Server Side Token Check + +With the `IdentityPool` CDK Construct, by default the pool is configured to check with the integrated user pools to +make sure that the user has not been globally signed out or deleted before the identity pool provides an OIDC token or +AWS credentials for the user. + +If the user is signed out or deleted, the identity pool will return a 400 Not Authorized error. This setting can be +disabled, however, in several ways. + +Setting `disableServerSideTokenCheck` to true will change the default behavior to no server side token check. Learn +more [here](https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_CognitoIdentityProvider.html#CognitoIdentity-Type-CognitoIdentityProvider-ServerSideTokenCheck): + +```ts +const userPool = new cognito.UserPool(this, 'Pool'); +identityPool.addUserPoolAuthentication({ + userPool: new UserPoolAuthenticationProvider({ + userPool, + disableServerSideTokenCheck: true, + }), +}); +``` + +#### Associating an External Provider Directly + +One or more [external identity providers](https://docs.aws.amazon.com/cognito/latest/developerguide/external-identity-providers.html) can be associated with an identity pool directly using +`authenticationProviders`: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + authenticationProviders: { + amazon: { + appId: 'amzn1.application.12312k3j234j13rjiwuenf', + }, + facebook: { + appId: '1234567890123', + }, + google: { + clientId: '12345678012.apps.googleusercontent.com', + } + apple: { + servicesId: 'com.myappleapp.auth', + }, + twitter: { + consumerKey: 'my-twitter-id', + consumerSecret: 'my-twitter-secret', + }, + }, +}); +``` + +To associate more than one provider of the same type with the identity pool, use User +Pools, OpenIdConnect, or SAML. Only one provider per external service can be attached directly to the identity pool. + +#### OpenId Connect and Saml + +[OpenID Connect](https://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html) is an open standard for +authentication that is supported by a number of login providers. Amazon Cognito supports linking of identities with +OpenID Connect providers that are configured through [AWS Identity and Access Management](http://aws.amazon.com/iam/). + +An identity provider that supports [Security Assertion Markup Language 2.0 (SAML 2.0)](https://docs.aws.amazon.com/cognito/latest/developerguide/saml-identity-provider.html) can be used to provide a simple +onboarding flow for users. The SAML-supporting identity provider specifies the IAM roles that can be assumed by users +so that different users can be granted different sets of permissions. Associating an OpenId Connect or Saml provider +with an identity pool: + +```ts +const openIdConnectProvider = new iam.OpenIdConnectProvider(this, 'my-openid-connect-provider', ...); +const samlProvider = new iam.SamlProvider(this, 'my-saml-provider', ...); + +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + authenticationProviders: { + openIdConnectProvider: openIdConnectProvider, + samlProvider: samlProvider, + } +}); +``` + +#### Custom Providers + +The identity pool's behavior can be customized further using custom [developer authenticated identities](https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html). +With developer authenticated identities, users can be registered and authenticated via an existing authentication +process while still using Amazon Cognito to synchronize user data and access AWS resources. + +Like the supported external providers, though, only one custom provider can be directly associated with the identity +pool. + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + authenticationProviders: { + google: '12345678012.apps.googleusercontent.com', + openIdConnectProvider: openIdConnectProvider, + customProvider: 'my-custom-provider.example.com', + } +}); +``` + +### Role Mapping + +In addition to setting default roles for authenticated and unauthenticated users, identity pools can also be used to +define rules to choose the role for each user based on claims in the user's ID token by using Role Mapping. When using +role mapping, it's important to be aware of some of the permissions the role will need. An in depth +review of roles and role mapping can be found [here](https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html). + +Using a [token-based approach](https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html#using-tokens-to-assign-roles-to-users) to role mapping will allow mapped roles to be passed through the `cognito:roles` or +`cognito:preferred_role` claims from the identity provider: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.AMAZON, + useToken: true, + }], +}); +``` + +Using a rule-based approach to role mapping allows roles to be assigned based on custom claims passed from the identity provider: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + // Assign specific roles to users based on whether or not the custom admin claim is passed from the identity provider + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.AMAZON, + rules: [ + { + claim: 'custom:admin', + claimValue: 'admin', + mappedRole: adminRole, + }, + { + claim: 'custom:admin', + claimValue: 'admin', + matchType: RoleMappingMatchType.NOTEQUAL, + mappedRole: nonAdminRole, + } + ], + }], +}); +``` + +Role mappings can also be added after instantiation with the Identity Pool's `addRoleMappings` method: + +```ts +identityPool.addRoleMappings(myAddedRoleMapping1, myAddedRoleMapping2, myAddedRoleMapping3); +``` + +#### Provider Urls + +Role mappings must be associated with the url of an Identity Provider which can be supplied +`IdentityPoolProviderUrl`. Supported Providers have static Urls that can be used: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.FACEBOOK, + useToken: true, + }], +}); +``` + +For identity providers that don't have static Urls, a custom Url or User Pool Client Url can be supplied: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + roleMappings: [ + { + providerUrl: IdentityPoolProviderUrl.userPool('cognito-idp.my-idp-region.amazonaws.com/my-idp-region_abcdefghi:app_client_id'), + useToken: true, + }, + { + providerUrl: IdentityPoolProviderUrl.custom('my-custom-provider.com'), + useToken: true, + }, + ], +}); +``` + +See [here](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypoolroleattachment-rolemapping.html#cfn-cognito-identitypoolroleattachment-rolemapping-identityprovider) for more information. + +### Authentication Flow + +Identity Pool [Authentication Flow](https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html) defaults to the enhanced, simplified flow. The Classic (basic) Authentication Flow +can also be implemented using `allowClassicFlow`: + +```ts +new cognito.IdentityPool(this, 'myidentitypool', { + identityPoolName: 'myidentitypool', + allowClassicFlow: true, +}); +``` + +### Cognito Sync + +It's now recommended to integrate [AWS AppSync](https://aws.amazon.com/appsync/) for synchronizing app data across devices, so +Cognito Sync features like `PushSync`, `CognitoEvents`, and `CognitoStreams` are not a part of `IdentityPool`. More +information can be found [here](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-sync.html). + +### Importing Identity Pools + +You can import existing identity pools into your stack using Identity Pool static methods with the Identity Pool Id or +Arn: + +```ts +IdentityPool.fromIdentityPoolId(this, 'my-imported-identity-pool', + 'us-east-1:dj2823ryiwuhef937'); +IdentityPool.fromIdentityPoolArn(this, 'my-imported-identity-pool', + 'arn:aws:cognito-identity:us-east-1:123456789012:identitypool/us-east-1:dj2823ryiwuhef937'); +``` + diff --git a/packages/@aws-cdk/aws-cognito-identitypool/jest.config.js b/packages/@aws-cdk/aws-cognito-identitypool/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-role-attachment.ts b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-role-attachment.ts new file mode 100644 index 0000000000000..b3811d99de5f3 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-role-attachment.ts @@ -0,0 +1,203 @@ +import { + CfnIdentityPoolRoleAttachment, +} from '@aws-cdk/aws-cognito'; +import { + IRole, +} from '@aws-cdk/aws-iam'; +import { + Resource, + IResource, +} from '@aws-cdk/core'; +import { + Construct, +} from 'constructs'; +import { + IIdentityPool, + IdentityPoolProviderUrl, +} from './identitypool'; + +/** + * Represents an Identity Pool Role Attachment + */ +export interface IIdentityPoolRoleAttachment extends IResource { + /** + * Id of the Attachments Underlying Identity Pool + */ + readonly identityPoolId: string; +} + +/** + * Props for an Identity Pool Role Attachment + */ +export interface IdentityPoolRoleAttachmentProps { + + /** + * Id of the Attachments Underlying Identity Pool + */ + readonly identityPool: IIdentityPool; + + /** + * Default Authenticated (User) Role + * @default - No default authenticated role will be added + */ + readonly authenticatedRole?: IRole; + + /** + * Default Unauthenticated (Guest) Role + * @default - No default unauthenticated role will be added + */ + readonly unauthenticatedRole?: IRole; + + /** + * Rules for mapping roles to users + * @default - no Role Mappings + */ + readonly roleMappings?: IdentityPoolRoleMapping[]; +} + +/** + * Map roles to users in the identity pool based on claims from the Identity Provider + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypoolroleattachment.html + */ +export interface IdentityPoolRoleMapping { + /** + * The url of the provider of for which the role is mapped + */ + readonly providerUrl: IdentityPoolProviderUrl; + + /** + * If true then mapped roles must be passed through the cognito:roles or cognito:preferred_role claims from identity provider. + * @see https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html#using-tokens-to-assign-roles-to-users + * + * @default false + */ + readonly useToken?: boolean; + + /** + * Allow for role assumption when results of role mapping are ambiguous + * @default false - Ambiguous role resolutions will lead to requester being denied + */ + readonly resolveAmbiguousRoles?: boolean; + + /** + * The claim and value that must be matched in order to assume the role. Required if useToken is false + * @default - No Rule Mapping Rule + */ + readonly rules?: RoleMappingRule[]; +} + +/** + * Types of matches allowed for Role Mapping + */ +export enum RoleMappingMatchType { + /** + * The Claim from the token must equal the given value in order for a match + */ + EQUALS = 'Equals', + + /** + * The Claim from the token must contain the given value in order for a match + */ + CONTAINS = 'Contains', + + /** + * The Claim from the token must start with the given value in order for a match + */ + STARTS_WITH = 'StartsWith', + + /** + * The Claim from the token must not equal the given value in order for a match + */ + NOTEQUAL = 'NotEqual', +} + +/** + * Represents an Identity Pool Role Attachment Role Mapping Rule + */ +export interface RoleMappingRule { + /** + * The key sent in the token by the federated identity provider. + */ + readonly claim: string; + + /** + * The Role to be assumed when Claim Value is matched. + */ + readonly mappedRole: IRole; + + /** + * The value of the claim that must be matched + */ + readonly claimValue: string; + + /** + * How to match with the Claim value + * @default RoleMappingMatchType.EQUALS + */ + readonly matchType?: RoleMappingMatchType +} + +/** + * Defines an Identity Pool Role Attachment + * + * @resource AWS::Cognito::IdentityPoolRoleAttachment + */ +export class IdentityPoolRoleAttachment extends Resource implements IIdentityPoolRoleAttachment { + /** + * Id of the underlying identity pool + */ + public readonly identityPoolId: string + + constructor(scope: Construct, id: string, props: IdentityPoolRoleAttachmentProps) { + super(scope, id); + this.identityPoolId = props.identityPool.identityPoolId; + const mappings = props.roleMappings || []; + let roles: any = undefined, roleMappings: any = undefined; + if (props.authenticatedRole || props.unauthenticatedRole) { + roles = {}; + if (props.authenticatedRole) roles.authenticated = props.authenticatedRole.roleArn; + if (props.unauthenticatedRole) roles.unauthenticated = props.unauthenticatedRole.roleArn; + } + if (mappings) { + roleMappings = this.configureRoleMappings(...mappings); + } + new CfnIdentityPoolRoleAttachment(this, 'Resource', { + identityPoolId: this.identityPoolId, + roles, + roleMappings, + }); + } + + /** + * Configures Role Mappings for Identity Pool Role Attachment + */ + private configureRoleMappings( + ...props: IdentityPoolRoleMapping[] + ): { [name:string]: CfnIdentityPoolRoleAttachment.RoleMappingProperty } | undefined { + if (!props || !props.length) return undefined; + return props.reduce((acc, prop) => { + let roleMapping: any = { + ambiguousRoleResolution: prop.resolveAmbiguousRoles ? 'AuthenticatedRole' : 'Deny', + type: prop.useToken ? 'Token' : 'Rules', + identityProvider: prop.providerUrl.value, + }; + if (roleMapping.type === 'Rules') { + if (!prop.rules) { + throw new Error('IdentityPoolRoleMapping.rules is required when useToken is false'); + } + roleMapping.rulesConfiguration = { + rules: prop.rules.map(rule => { + return { + claim: rule.claim, + value: rule.claimValue, + matchType: rule.matchType || RoleMappingMatchType.EQUALS, + roleArn: rule.mappedRole.roleArn, + }; + }), + }; + }; + acc[prop.providerUrl.value] = roleMapping; + return acc; + }, {} as { [name:string]: CfnIdentityPoolRoleAttachment.RoleMappingProperty }); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-user-pool-authentication-provider.ts b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-user-pool-authentication-provider.ts new file mode 100644 index 0000000000000..831d223250258 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool-user-pool-authentication-provider.ts @@ -0,0 +1,118 @@ +import { + IUserPool, + IUserPoolClient, +} from '@aws-cdk/aws-cognito'; +import { Stack } from '@aws-cdk/core'; +import { + Construct, Node, +} from 'constructs'; +import { IIdentityPool } from './identitypool'; + +/** + * Represents the concept of a User Pool Authentication Provider. + * You use user pool authentication providers to configure User Pools + * and User Pool Clients for use with Identity Pools + */ +export interface IUserPoolAuthenticationProvider { + /** + * The method called when a given User Pool Authentication Provider is added + * (for the first time) to an Identity Pool. + */ + bind( + scope: Construct, + identityPool: IIdentityPool, + options?: UserPoolAuthenticationProviderBindOptions + ): UserPoolAuthenticationProviderBindConfig; +} + +/** + * Props for the User Pool Authentication Provider + */ +export interface UserPoolAuthenticationProviderProps { + /** + * The User Pool of the Associated Identity Providers + */ + readonly userPool: IUserPool; + + /** + * The User Pool Client for the provided User Pool + * @default - A default user pool client will be added to User Pool + */ + readonly userPoolClient?: IUserPoolClient; + + /** + * Setting this to true turns off identity pool checks for this user pool to make sure the user has not been globally signed out or deleted before the identity pool provides an OIDC token or AWS credentials for the user + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypool-cognitoidentityprovider.html + * @default false + */ + readonly disableServerSideTokenCheck?: boolean; + +} + +/** + * Represents UserPoolAuthenticationProvider Bind Options + */ +export interface UserPoolAuthenticationProviderBindOptions {} + +/** + * Represents a UserPoolAuthenticationProvider Bind Configuration + */ +export interface UserPoolAuthenticationProviderBindConfig { + /** + * Client Id of the Associated User Pool Client + */ + readonly clientId: string + + /** + * The identity providers associated with the UserPool + */ + readonly providerName: string; + + /** + * Whether to enable the identity pool's server side token check + */ + readonly serverSideTokenCheck: boolean; +} + +/** + * Defines a User Pool Authentication Provider + */ +export class UserPoolAuthenticationProvider implements IUserPoolAuthenticationProvider { + + /** + * The User Pool of the Associated Identity Providers + */ + private userPool: IUserPool; + + /** + * The User Pool Client for the provided User Pool + */ + private userPoolClient: IUserPoolClient; + + /** + * Whether to disable the pool's default server side token check + */ + private disableServerSideTokenCheck: boolean + constructor(props: UserPoolAuthenticationProviderProps) { + this.userPool = props.userPool; + this.userPoolClient = props.userPoolClient || this.userPool.addClient('UserPoolAuthenticationProviderClient'); + this.disableServerSideTokenCheck = props.disableServerSideTokenCheck ?? false; + } + + public bind( + scope: Construct, + identityPool: IIdentityPool, + _options?: UserPoolAuthenticationProviderBindOptions, + ): UserPoolAuthenticationProviderBindConfig { + Node.of(identityPool).addDependency(this.userPool); + Node.of(identityPool).addDependency(this.userPoolClient); + const region = Stack.of(scope).region; + const urlSuffix = Stack.of(scope).urlSuffix; + + return { + clientId: this.userPoolClient.userPoolClientId, + providerName: `cognito-idp.${region}.${urlSuffix}/${this.userPool.userPoolId}`, + serverSideTokenCheck: !this.disableServerSideTokenCheck, + }; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool.ts b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool.ts new file mode 100644 index 0000000000000..cefab0caa54d9 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/lib/identitypool.ts @@ -0,0 +1,490 @@ +import { + CfnIdentityPool, +} from '@aws-cdk/aws-cognito'; +import { + IOpenIdConnectProvider, + ISamlProvider, + Role, + FederatedPrincipal, + IRole, +} from '@aws-cdk/aws-iam'; +import { + Resource, + IResource, + Stack, + ArnFormat, + Lazy, +} from '@aws-cdk/core'; +import { + Construct, +} from 'constructs'; +import { + IdentityPoolRoleAttachment, + IdentityPoolRoleMapping, +} from './identitypool-role-attachment'; +import { + IUserPoolAuthenticationProvider, +} from './identitypool-user-pool-authentication-provider'; + +/** + * Represents a Cognito IdentityPool + */ +export interface IIdentityPool extends IResource { + /** + * The id of the Identity Pool in the format REGION:GUID + * @attribute + */ + readonly identityPoolId: string; + + /** + * The ARN of the Identity Pool + * @attribute + */ + readonly identityPoolArn: string; + + /** + * Name of the Identity Pool + * @attribute + */ + readonly identityPoolName: string +} + +/** + * Props for the IdentityPool construct + */ +export interface IdentityPoolProps { + + /** + * The name of the Identity Pool + * @default - automatically generated name by CloudFormation at deploy time + */ + readonly identityPoolName?: string; + + /** + * The Default Role to be assumed by Authenticated Users + * @default - A Default Authenticated Role will be added + */ + readonly authenticatedRole?: IRole; + + /** + * The Default Role to be assumed by Unauthenticated Users + * @default - A Default Unauthenticated Role will be added + */ + readonly unauthenticatedRole?: IRole; + + /** + * Wwhether the identity pool supports unauthenticated logins + * @default - false + */ + readonly allowUnauthenticatedIdentities?: boolean + + /** + * Rules for mapping roles to users + * @default - no Role Mappings + */ + readonly roleMappings?: IdentityPoolRoleMapping[]; + + /** + * Enables the Basic (Classic) authentication flow + * @default - Classic Flow not allowed + */ + readonly allowClassicFlow?: boolean; + + /** + * Authentication providers for using in identity pool. + * @default - No Authentication Providers passed directly to Identity Pool + */ + readonly authenticationProviders?: IdentityPoolAuthenticationProviders +} + +/** + * Types of Identity Pool Login Providers + */ +export enum IdentityPoolProviderType { + /** Facebook Provider type */ + FACEBOOK = 'Facebook', + /** Google Provider Type */ + GOOGLE = 'Google', + /** Amazon Provider Type */ + AMAZON = 'Amazon', + /** Apple Provider Type */ + APPLE = 'Apple', + /** Twitter Provider Type */ + TWITTER = 'Twitter', + /** Digits Provider Type */ + DIGITS = 'Digits', + /** Open Id Provider Type */ + OPEN_ID = 'OpenId', + /** Saml Provider Type */ + SAML = 'Saml', + /** User Pool Provider Type */ + USER_POOL = 'UserPool', + /** Custom Provider Type */ + CUSTOM = 'Custom', +} + +/** + * Keys for Login Providers - correspond to client id's of respective federation identity providers + */ +export class IdentityPoolProviderUrl { + /** Facebook Provider Url */ + public static readonly FACEBOOK = new IdentityPoolProviderUrl(IdentityPoolProviderType.FACEBOOK, 'graph.facebook.com'); + + /** Google Provider Url */ + public static readonly GOOGLE = new IdentityPoolProviderUrl(IdentityPoolProviderType.GOOGLE, 'accounts.google.com'); + + /** Amazon Provider Url */ + public static readonly AMAZON = new IdentityPoolProviderUrl(IdentityPoolProviderType.AMAZON, 'www.amazon.com'); + + /** Apple Provider Url */ + public static readonly APPLE = new IdentityPoolProviderUrl(IdentityPoolProviderType.APPLE, 'appleid.apple.com'); + + /** Twitter Provider Url */ + public static readonly TWITTER = new IdentityPoolProviderUrl(IdentityPoolProviderType.TWITTER, 'api.twitter.com'); + + /** Digits Provider Url */ + public static readonly DIGITS = new IdentityPoolProviderUrl(IdentityPoolProviderType.DIGITS, 'www.digits.com'); + + /** OpenId Provider Url */ + public static openId(url: string): IdentityPoolProviderUrl { + return new IdentityPoolProviderUrl(IdentityPoolProviderType.OPEN_ID, url); + } + + /** Saml Provider Url */ + public static saml(url: string): IdentityPoolProviderUrl { + return new IdentityPoolProviderUrl(IdentityPoolProviderType.SAML, url); + } + + /** User Pool Provider Url */ + public static userPool(url: string): IdentityPoolProviderUrl { + return new IdentityPoolProviderUrl(IdentityPoolProviderType.USER_POOL, url); + } + + /** Custom Provider Url */ + public static custom(url: string): IdentityPoolProviderUrl { + return new IdentityPoolProviderUrl(IdentityPoolProviderType.CUSTOM, url); + } + + constructor( + /** type of Provider Url */ + public readonly type: IdentityPoolProviderType, + /** value of Provider Url */ + public readonly value: string, + ) {} +} + +/** + * Login Provider for Identity Federation using Amazon Credentials + */ +export interface IdentityPoolAmazonLoginProvider { + /** + * App Id for Amazon Identity Federation + */ + readonly appId: string +} + +/** + * Login Provider for Identity Federation using Facebook Credentials + */ +export interface IdentityPoolFacebookLoginProvider { + /** + * App Id for Facebook Identity Federation + */ + readonly appId: string +} + +/** + * Login Provider for Identity Federation using Apple Credentials +*/ +export interface IdentityPoolAppleLoginProvider { + /** + * App Id for Apple Identity Federation + */ + readonly servicesId: string +} + +/** + * Login Provider for Identity Federation using Google Credentials + */ +export interface IdentityPoolGoogleLoginProvider { + /** + * App Id for Google Identity Federation + */ + readonly clientId: string +} + +/** + * Login Provider for Identity Federation using Twitter Credentials + */ +export interface IdentityPoolTwitterLoginProvider { + /** + * App Id for Twitter Identity Federation + */ + readonly consumerKey: string + + /** + * App Secret for Twitter Identity Federation + */ + readonly consumerSecret: string +} + +/** + * Login Provider for Identity Federation using Digits Credentials + */ +export interface IdentityPoolDigitsLoginProvider extends IdentityPoolTwitterLoginProvider {} + +/** + * External Identity Providers To Connect to User Pools and Identity Pools + */ +export interface IdentityPoolProviders { + + /** App Id for Facebook Identity Federation + * @default - No Facebook Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly facebook?: IdentityPoolFacebookLoginProvider + + /** Client Id for Google Identity Federation + * @default - No Google Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly google?: IdentityPoolGoogleLoginProvider + + /** App Id for Amazon Identity Federation + * @default - No Amazon Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly amazon?: IdentityPoolAmazonLoginProvider + + /** Services Id for Apple Identity Federation + * @default - No Apple Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly apple?: IdentityPoolAppleLoginProvider + + /** Consumer Key and Secret for Twitter Identity Federation + * @default - No Twitter Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly twitter?: IdentityPoolTwitterLoginProvider + + /** Consumer Key and Secret for Digits Identity Federation + * @default - No Digits Authentication Provider used without OpenIdConnect or a User Pool + */ + readonly digits?: IdentityPoolDigitsLoginProvider +} + +/** +* Authentication providers for using in identity pool. +* @see https://docs.aws.amazon.com/cognito/latest/developerguide/external-identity-providers.html +*/ +export interface IdentityPoolAuthenticationProviders extends IdentityPoolProviders { + + /** + * The User Pool Authentication Providers associated with this Identity Pool + * @default - no User Pools Associated + */ + readonly userPools?: IUserPoolAuthenticationProvider[]; + + /** + * The OpenIdConnect Provider associated with this Identity Pool + * @default - no OpenIdConnectProvider + */ + readonly openIdConnectProviders?: IOpenIdConnectProvider[]; + + /** + * The Security Assertion Markup Language Provider associated with this Identity Pool + * @default - no SamlProvider + */ + readonly samlProviders?: ISamlProvider[]; + + /** + * The Developer Provider Name to associate with this Identity Pool + * @default - no Custom Provider + */ + readonly customProvider?: string; +} + +/** + * Define a Cognito Identity Pool + * + * @resource AWS::Cognito::IdentityPool + */ +export class IdentityPool extends Resource implements IIdentityPool { + + /** + * Import an existing Identity Pool from its id + */ + public static fromIdentityPoolId(scope: Construct, id: string, identityPoolId: string): IIdentityPool { + const identityPoolArn = Stack.of(scope).formatArn({ + service: 'cognito-identity', + resource: 'identitypool', + resourceName: identityPoolId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + + return IdentityPool.fromIdentityPoolArn(scope, id, identityPoolArn); + } + + /** + * Import an existing Identity Pool from its Arn + */ + public static fromIdentityPoolArn(scope: Construct, id: string, identityPoolArn: string): IIdentityPool { + const pool = Stack.of(scope).splitArn(identityPoolArn, ArnFormat.SLASH_RESOURCE_NAME); + const res = pool.resourceName || ''; + if (!res) { + throw new Error('Invalid Identity Pool ARN'); + } + const idParts = res.split(':'); + if (!(idParts.length === 2)) throw new Error('Invalid Identity Pool Id: Identity Pool Ids must follow the format :'); + if (idParts[0] !== pool.region) throw new Error('Invalid Identity Pool Id: Region in Identity Pool Id must match stack region'); + class ImportedIdentityPool extends Resource implements IIdentityPool { + public readonly identityPoolId = res; + public readonly identityPoolArn = identityPoolArn; + public readonly identityPoolName: string + constructor() { + super(scope, id, { + account: pool.account, + region: pool.region, + }); + this.identityPoolName = this.physicalName; + } + } + return new ImportedIdentityPool(); + } + + /** + * The id of the Identity Pool in the format REGION:GUID + * @attribute + */ + public readonly identityPoolId: string; + + /** + * The ARN of the Identity Pool + * @attribute + */ + public readonly identityPoolArn: string; + + /** + * The name of the Identity Pool + * @attribute + */ + public readonly identityPoolName: string; + + /** + * Default role for authenticated users + */ + public readonly authenticatedRole: IRole; + + /** + * Default role for unauthenticated users + */ + public readonly unauthenticatedRole: IRole; + + /** + * List of Identity Providers added in constructor for use with property overrides + */ + private cognitoIdentityProviders: CfnIdentityPool.CognitoIdentityProviderProperty[] = []; + + /** + * Running count of added role attachments + */ + private roleAttachmentCount: number = 0; + + constructor(scope: Construct, id: string, props:IdentityPoolProps = {}) { + super(scope, id, { + physicalName: props.identityPoolName, + }); + const authProviders: IdentityPoolAuthenticationProviders = props.authenticationProviders || {}; + const providers = authProviders.userPools ? authProviders.userPools.map(userPool => userPool.bind(this, this)) : undefined; + if (providers && providers.length) this.cognitoIdentityProviders = providers; + const openIdConnectProviderArns = authProviders.openIdConnectProviders ? + authProviders.openIdConnectProviders.map(openIdProvider => + openIdProvider.openIdConnectProviderArn, + ) : undefined; + const samlProviderArns = authProviders.samlProviders ? + authProviders.samlProviders.map(samlProvider => + samlProvider.samlProviderArn, + ) : undefined; + + let supportedLoginProviders:any = {}; + if (authProviders.amazon) supportedLoginProviders[IdentityPoolProviderUrl.AMAZON.value] = authProviders.amazon.appId; + if (authProviders.facebook) supportedLoginProviders[IdentityPoolProviderUrl.FACEBOOK.value] = authProviders.facebook.appId; + if (authProviders.google) supportedLoginProviders[IdentityPoolProviderUrl.GOOGLE.value] = authProviders.google.clientId; + if (authProviders.apple) supportedLoginProviders[IdentityPoolProviderUrl.APPLE.value] = authProviders.apple.servicesId; + if (authProviders.twitter) supportedLoginProviders[IdentityPoolProviderUrl.TWITTER.value] = `${authProviders.twitter.consumerKey};${authProviders.twitter.consumerSecret}`; + if (authProviders.digits) supportedLoginProviders[IdentityPoolProviderUrl.DIGITS.value] = `${authProviders.digits.consumerKey};${authProviders.digits.consumerSecret}`; + if (!Object.keys(supportedLoginProviders).length) supportedLoginProviders = undefined; + + const cfnIdentityPool = new CfnIdentityPool(this, 'Resource', { + allowUnauthenticatedIdentities: props.allowUnauthenticatedIdentities ? true : false, + allowClassicFlow: props.allowClassicFlow, + identityPoolName: this.physicalName, + developerProviderName: authProviders.customProvider, + openIdConnectProviderArns, + samlProviderArns, + supportedLoginProviders, + cognitoIdentityProviders: Lazy.any({ produce: () => this.cognitoIdentityProviders }), + }); + this.identityPoolName = cfnIdentityPool.attrName; + this.identityPoolId = cfnIdentityPool.ref; + this.identityPoolArn = Stack.of(scope).formatArn({ + service: 'cognito-identity', + resource: 'identitypool', + resourceName: this.identityPoolId, + arnFormat: ArnFormat.SLASH_RESOURCE_NAME, + }); + this.authenticatedRole = props.authenticatedRole ? props.authenticatedRole : this.configureDefaultRole('Authenticated'); + this.unauthenticatedRole = props.unauthenticatedRole ? props.unauthenticatedRole : this.configureDefaultRole('Unauthenticated'); + const attachment = new IdentityPoolRoleAttachment(this, 'DefaultRoleAttachment', { + identityPool: this, + authenticatedRole: this.authenticatedRole, + unauthenticatedRole: this.unauthenticatedRole, + roleMappings: props.roleMappings, + }); + attachment.node.addDependency(this); + } + + /** + * Add a User Pool to the IdentityPool and configure User Pool Client to handle identities + */ + public addUserPoolAuthentication(userPool: IUserPoolAuthenticationProvider): void { + const providers = userPool.bind(this, this); + this.cognitoIdentityProviders = this.cognitoIdentityProviders.concat(providers); + } + + /** + * Adds Role Mappings to Identity Pool + */ + public addRoleMappings(...roleMappings: IdentityPoolRoleMapping[]): void { + if (!roleMappings || !roleMappings.length) return; + this.roleAttachmentCount++; + const name = 'RoleMappingAttachment' + this.roleAttachmentCount.toString(); + const attachment = new IdentityPoolRoleAttachment(this, name, { + identityPool: this, + authenticatedRole: this.authenticatedRole, + unauthenticatedRole: this.unauthenticatedRole, + roleMappings, + }); + attachment.node.addDependency(this); + } + + /** + * Configure Default Roles For Identity Pool + */ + private configureDefaultRole(type: string): IRole { + const assumedBy = this.configureDefaultGrantPrincipal(type.toLowerCase()); + const role = new Role(this, `${type}Role`, { + description: `Default ${type} Role for Identity Pool ${this.identityPoolName}`, + assumedBy, + }); + + return role; + } + + private configureDefaultGrantPrincipal(type: string) { + return new FederatedPrincipal('cognito-identity.amazonaws.com', { + 'StringEquals': { + 'cognito-identity.amazonaws.com:aud': this.identityPoolId, + }, + 'ForAnyValue:StringLike': { + 'cognito-identity.amazonaws.com:amr': type, + }, + }, 'sts:AssumeRoleWithWebIdentity'); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/lib/index.ts b/packages/@aws-cdk/aws-cognito-identitypool/lib/index.ts new file mode 100644 index 0000000000000..f24f1f580225b --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/lib/index.ts @@ -0,0 +1,3 @@ +export * from './identitypool'; +export * from './identitypool-role-attachment'; +export * from './identitypool-user-pool-authentication-provider'; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/package.json b/packages/@aws-cdk/aws-cognito-identitypool/package.json new file mode 100644 index 0000000000000..e7b9183ce8ba7 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-cdk/aws-cognito-identitypool", + "version": "0.0.0", + "description": "The CDK Construct Library for AWS::Cognito Identity Pools", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "targets": { + "java": { + "package": "software.amazon.awscdk.services.cognito.identitypool", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "cognito-identitypool" + } + }, + "dotnet": { + "namespace": "Amazon.CDK.AWS.Cognito.IdentityPool", + "packageId": "Amazon.CDK.AWS.Cognito.IdentityPool", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "python": { + "distName": "aws-cdk.aws-cognito-identitypool", + "module": "aws_cdk.aws_cognito_identitypool", + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ] + } + }, + "projectReferences": true + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-cognito-identitypool" + }, + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "build+test+package": "yarn build+test && yarn package", + "build+test": "yarn build && yarn test", + "compat": "cdk-compat", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "env": { + "AWSLINT_BASE_CONSTRUCT": true + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "cognito", + "identitypool" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cdk-integ-tools": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.0.3", + "jest": "^27.4.5" + }, + "dependencies": { + "@aws-cdk/aws-cognito": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "homepage": "https://github.com/aws/aws-cdk", + "peerDependencies": { + "@aws-cdk/aws-cognito": "0.0.0", + "@aws-cdk/aws-iam": "0.0.0", + "@aws-cdk/core": "0.0.0", + "constructs": "^3.3.69" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "awslint": { + "exclude": [ + "no-unused-type:@aws-cdk/aws-cognito.IdentityPoolProviderType", + "props-physical-name:@aws-cdk/aws-cognito-identitypool.IdentityPoolRoleAttachmentProps" + ] + }, + "stability": "experimental", + "maturity": "experimental", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-cognito-identitypool/test/identitypool.test.ts b/packages/@aws-cdk/aws-cognito-identitypool/test/identitypool.test.ts new file mode 100644 index 0000000000000..903c3915a0e11 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/test/identitypool.test.ts @@ -0,0 +1,611 @@ +import { + Template, +} from '@aws-cdk/assertions'; +import { + UserPool, + UserPoolIdentityProvider, +} from '@aws-cdk/aws-cognito'; +import { + Role, + ServicePrincipal, + ArnPrincipal, + AnyPrincipal, + OpenIdConnectProvider, + SamlProvider, + SamlMetadataDocument, + PolicyStatement, + Effect, + PolicyDocument, +} from '@aws-cdk/aws-iam'; +import { + Stack, +} from '@aws-cdk/core'; +import { + IdentityPool, + IdentityPoolProviderUrl, +} from '../lib/identitypool'; +import { + RoleMappingMatchType, +} from '../lib/identitypool-role-attachment'; +import { UserPoolAuthenticationProvider } from '../lib/identitypool-user-pool-authentication-provider'; + +describe('identity pool', () => { + test('minimal setup', () => { + const stack = new Stack(); + new IdentityPool(stack, 'TestIdentityPoolMinimal'); + const temp = Template.fromStack(stack); + + temp.hasResourceProperties('AWS::Cognito::IdentityPool', { + AllowUnauthenticatedIdentities: false, + }); + + temp.resourceCountIs('AWS::IAM::Role', 2); + temp.resourceCountIs('AWS::IAM::Policy', 0); + temp.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRoleWithWebIdentity', + Condition: { + 'StringEquals': { + 'cognito-identity.amazonaws.com:aud': { + Ref: 'TestIdentityPoolMinimal44837852', + }, + }, + 'ForAnyValue:StringLike': { + 'cognito-identity.amazonaws.com:amr': 'authenticated', + }, + }, + Effect: 'Allow', + Principal: { + Federated: 'cognito-identity.amazonaws.com', + }, + }, + ], + }, + }); + + temp.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRoleWithWebIdentity', + Condition: { + 'StringEquals': { + 'cognito-identity.amazonaws.com:aud': { + Ref: 'TestIdentityPoolMinimal44837852', + }, + }, + 'ForAnyValue:StringLike': { + 'cognito-identity.amazonaws.com:amr': 'unauthenticated', + }, + }, + Effect: 'Allow', + Principal: { + Federated: 'cognito-identity.amazonaws.com', + }, + }, + ], + }, + }); + }); + + test('providing default roles directly', () => { + const stack = new Stack(); + const authenticatedRole = new Role(stack, 'authRole', { + assumedBy: new ServicePrincipal('service.amazonaws.com'), + }); + const unauthenticatedRole = new Role(stack, 'unauthRole', { + assumedBy: new ServicePrincipal('service.amazonaws.com'), + }); + const identityPool = new IdentityPool(stack, 'TestIdentityPoolActions', { + authenticatedRole, unauthenticatedRole, allowUnauthenticatedIdentities: true, + }); + identityPool.authenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['execute-api:*', 'dynamodb:*'], + resources: ['*'], + })); + identityPool.unauthenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['execute-api:*'], + resources: ['arn:aws:execute-api:us-east-1:*:my-api/prod'], + })); + const temp = Template.fromStack(stack); + temp.resourceCountIs('AWS::IAM::Role', 2); + temp.resourceCountIs('AWS::IAM::Policy', 2); + temp.hasResourceProperties('AWS::Cognito::IdentityPool', { + AllowUnauthenticatedIdentities: true, + }); + temp.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + Service: 'service.amazonaws.com', + }, + }, + ], + }, + }); + temp.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'execute-api:*', + Effect: 'Allow', + Resource: 'arn:aws:execute-api:us-east-1:*:my-api/prod', + }, + ], + }, + }); + + temp.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: ['execute-api:*', 'dynamodb:*'], + Effect: 'Allow', + Resource: '*', + }, + ], + }, + }); + }); + test('adding actions and resources to default roles', () => { + const stack = new Stack(); + const identityPool = new IdentityPool(stack, 'TestIdentityPoolActions'); + identityPool.authenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['execute-api:*', 'dynamodb:*'], + resources: ['*'], + })); + identityPool.unauthenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['execute-api:*'], + resources: ['arn:aws:execute-api:us-east-1:*:my-api/prod'], + })); + const temp = Template.fromStack(stack); + temp.resourceCountIs('AWS::IAM::Role', 2); + temp.resourceCountIs('AWS::IAM::Policy', 2); + temp.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: 'execute-api:*', + Effect: 'Allow', + Resource: 'arn:aws:execute-api:us-east-1:*:my-api/prod', + }, + ], + }, + }); + + temp.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Action: ['execute-api:*', 'dynamodb:*'], + Effect: 'Allow', + Resource: '*', + }, + ], + }, + }); + }); + + test('from static', () => { + const stack = new Stack(undefined, undefined, { + env: { + region: 'my-region', + account: '1234567891011', + }, + }); + expect(() => IdentityPool.fromIdentityPoolId(stack, 'idPoolIdError', 'idPool')).toThrowError('Invalid Identity Pool Id: Identity Pool Ids must follow the format :'); + expect(() => IdentityPool.fromIdentityPoolArn(stack, 'idPoolArnError', 'arn:aws:cognito-identity:my-region:1234567891011:identitypool\/your-region:idPool/')).toThrowError('Invalid Identity Pool Id: Region in Identity Pool Id must match stack region'); + const idPool = IdentityPool.fromIdentityPoolId(stack, 'staticIdPool', 'my-region:idPool'); + + expect(idPool.identityPoolId).toEqual('my-region:idPool'); + expect(idPool.identityPoolArn).toMatch(/cognito-identity:my-region:1234567891011:identitypool\/my-region:idPool/); + }); + + test('user pools are properly configured', () => { + const stack = new Stack(); + const poolProvider = UserPoolIdentityProvider.fromProviderName(stack, 'poolProvider', 'poolProvider'); + const otherPoolProvider = UserPoolIdentityProvider.fromProviderName(stack, 'otherPoolProvider', 'otherPoolProvider'); + const pool = new UserPool(stack, 'Pool'); + const otherPool = new UserPool(stack, 'OtherPool'); + pool.registerIdentityProvider(poolProvider); + otherPool.registerIdentityProvider(otherPoolProvider); + const idPool = new IdentityPool(stack, 'TestIdentityPoolUserPools', { + authenticationProviders: { + userPools: [new UserPoolAuthenticationProvider({ userPool: pool })], + }, + }); + idPool.addUserPoolAuthentication( + new UserPoolAuthenticationProvider({ + userPool: otherPool, + disableServerSideTokenCheck: true, + }), + ); + const temp = Template.fromStack(stack); + temp.resourceCountIs('AWS::Cognito::UserPool', 2); + temp.resourceCountIs('AWS::Cognito::UserPoolClient', 2); + temp.hasResourceProperties('AWS::Cognito::UserPoolClient', { + UserPoolId: { + Ref: 'PoolD3F588B8', + }, + AllowedOAuthFlows: [ + 'implicit', + 'code', + ], + AllowedOAuthFlowsUserPoolClient: true, + AllowedOAuthScopes: [ + 'profile', + 'phone', + 'email', + 'openid', + 'aws.cognito.signin.user.admin', + ], + CallbackURLs: [ + 'https://example.com', + ], + SupportedIdentityProviders: [ + 'poolProvider', + 'COGNITO', + ], + }); + temp.hasResourceProperties('AWS::Cognito::UserPoolClient', { + UserPoolId: { + Ref: 'OtherPool7DA7F2F7', + }, + AllowedOAuthFlows: [ + 'implicit', + 'code', + ], + AllowedOAuthFlowsUserPoolClient: true, + AllowedOAuthScopes: [ + 'profile', + 'phone', + 'email', + 'openid', + 'aws.cognito.signin.user.admin', + ], + CallbackURLs: [ + 'https://example.com', + ], + SupportedIdentityProviders: [ + 'otherPoolProvider', + 'COGNITO', + ], + }); + temp.hasResourceProperties('AWS::Cognito::IdentityPool', { + AllowUnauthenticatedIdentities: false, + CognitoIdentityProviders: [ + { + ClientId: { + Ref: 'PoolUserPoolAuthenticationProviderClient20F2FFC4', + }, + ProviderName: { + 'Fn::Join': [ + '', + [ + 'cognito-idp.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/', + { + Ref: 'PoolD3F588B8', + }, + ], + ], + }, + ServerSideTokenCheck: true, + }, + { + ClientId: { + Ref: 'OtherPoolUserPoolAuthenticationProviderClient08F670F8', + }, + ProviderName: { + 'Fn::Join': [ + '', + [ + 'cognito-idp.', + { + Ref: 'AWS::Region', + }, + '.', + { + Ref: 'AWS::URLSuffix', + }, + '/', + { + Ref: 'OtherPool7DA7F2F7', + }, + ], + ], + }, + ServerSideTokenCheck: false, + }, + ], + }); + }); + + test('openId, saml, classicFlow, customProviders', () => { + const stack = new Stack(); + const openId = new OpenIdConnectProvider(stack, 'OpenId', { + url: 'https://example.com', + clientIds: ['client1', 'client2'], + thumbprints: ['thumbprint'], + }); + const saml = new SamlProvider(stack, 'Provider', { + metadataDocument: SamlMetadataDocument.fromXml('document'), + }); + new IdentityPool(stack, 'TestIdentityPoolCustomProviders', { + authenticationProviders: { + openIdConnectProviders: [openId], + samlProviders: [saml], + customProvider: 'my-custom-provider.com', + }, + allowClassicFlow: true, + }); + const temp = Template.fromStack(stack); + temp.resourceCountIs('Custom::AWSCDKOpenIdConnectProvider', 1); + temp.resourceCountIs('AWS::IAM::SAMLProvider', 1); + temp.hasResourceProperties('AWS::Cognito::IdentityPool', { + AllowUnauthenticatedIdentities: false, + AllowClassicFlow: true, + DeveloperProviderName: 'my-custom-provider.com', + OpenIdConnectProviderARNs: [ + { + Ref: 'OpenId76D94D20', + }, + ], + SamlProviderARNs: [ + { + Ref: 'Provider2281708E', + }, + ], + }); + }); + + test('cognito authentication providers', () => { + const stack = new Stack(); + new IdentityPool(stack, 'TestIdentityPoolauthproviders', { + identityPoolName: 'my-id-pool', + authenticationProviders: { + amazon: { appId: 'amzn1.application.12312k3j234j13rjiwuenf' }, + google: { clientId: '12345678012.apps.googleusercontent.com' }, + }, + }); + const temp = Template.fromStack(stack); + temp.resourceCountIs('AWS::IAM::Role', 2); + temp.hasResourceProperties('AWS::Cognito::IdentityPool', { + IdentityPoolName: 'my-id-pool', + SupportedLoginProviders: { + 'www.amazon.com': 'amzn1.application.12312k3j234j13rjiwuenf', + 'accounts.google.com': '12345678012.apps.googleusercontent.com', + }, + }); + }); +}); + +describe('role mappings', () => { + test('using token', () => { + const stack = new Stack(); + new IdentityPool(stack, 'TestIdentityPoolRoleMappingToken', { + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.AMAZON, + useToken: true, + }], + }); + Template.fromStack(stack).hasResourceProperties('AWS::Cognito::IdentityPoolRoleAttachment', { + IdentityPoolId: { + Ref: 'TestIdentityPoolRoleMappingToken0B11D690', + }, + RoleMappings: { + 'www.amazon.com': { + AmbiguousRoleResolution: 'Deny', + IdentityProvider: 'www.amazon.com', + Type: 'Token', + }, + }, + Roles: { + authenticated: { + 'Fn::GetAtt': [ + 'TestIdentityPoolRoleMappingTokenAuthenticatedRoleD99CE043', + 'Arn', + ], + }, + unauthenticated: { + 'Fn::GetAtt': [ + 'TestIdentityPoolRoleMappingTokenUnauthenticatedRole1D86D800', + 'Arn', + ], + }, + }, + }); + }); + + test('rules type without rules throws', () => { + const stack = new Stack(); + expect(() => new IdentityPool(stack, 'TestIdentityPoolRoleMappingErrors', { + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.AMAZON, + }], + })).toThrowError('IdentityPoolRoleMapping.rules is required when useToken is false'); + }); + + test('role mapping with rules configuration', () => { + const stack = new Stack(); + const adminRole = new Role(stack, 'adminRole', { + assumedBy: new ServicePrincipal('admin.amazonaws.com'), + }); + const nonAdminRole = new Role(stack, 'nonAdminRole', { + assumedBy: new AnyPrincipal(), + inlinePolicies: { + DenyAll: new PolicyDocument({ + statements: [ + new PolicyStatement({ + effect: Effect.DENY, + actions: ['update:*', 'put:*', 'delete:*'], + resources: ['*'], + }), + ], + }), + }, + }); + const facebookRole = new Role(stack, 'facebookRole', { + assumedBy: new ArnPrincipal('arn:aws:iam::123456789012:user/FacebookUser'), + }); + const customRole = new Role(stack, 'customRole', { + assumedBy: new ArnPrincipal('arn:aws:iam::123456789012:user/CustomUser'), + }); + const idPool = new IdentityPool(stack, 'TestIdentityPoolRoleMappingRules', { + roleMappings: [{ + providerUrl: IdentityPoolProviderUrl.AMAZON, + resolveAmbiguousRoles: true, + rules: [ + { + claim: 'custom:admin', + claimValue: 'admin', + mappedRole: adminRole, + }, + { + claim: 'custom:admin', + claimValue: 'admin', + matchType: RoleMappingMatchType.NOTEQUAL, + mappedRole: nonAdminRole, + }, + ], + }], + }); + idPool.addRoleMappings({ + providerUrl: IdentityPoolProviderUrl.FACEBOOK, + rules: [ + { + claim: 'iss', + claimValue: 'https://graph.facebook.com', + mappedRole: facebookRole, + }, + ], + }, + { + providerUrl: IdentityPoolProviderUrl.custom('example.com'), + rules: [ + { + claim: 'iss', + claimValue: 'https://example.com', + mappedRole: customRole, + }, + ], + }); + const temp = Template.fromStack(stack); + temp.resourceCountIs('AWS::Cognito::IdentityPoolRoleAttachment', 2); + temp.hasResourceProperties('AWS::Cognito::IdentityPoolRoleAttachment', { + IdentityPoolId: { + Ref: 'TestIdentityPoolRoleMappingRulesC8C07BC3', + }, + RoleMappings: { + 'www.amazon.com': { + AmbiguousRoleResolution: 'AuthenticatedRole', + IdentityProvider: 'www.amazon.com', + RulesConfiguration: { + Rules: [ + { + Claim: 'custom:admin', + MatchType: 'Equals', + RoleARN: { + 'Fn::GetAtt': [ + 'adminRoleC345D70B', + 'Arn', + ], + }, + Value: 'admin', + }, + { + Claim: 'custom:admin', + MatchType: 'NotEqual', + RoleARN: { + 'Fn::GetAtt': [ + 'nonAdminRole43C19D5C', + 'Arn', + ], + }, + Value: 'admin', + }, + ], + }, + Type: 'Rules', + }, + }, + Roles: { + authenticated: { + 'Fn::GetAtt': [ + 'TestIdentityPoolRoleMappingRulesAuthenticatedRole14D102C7', + 'Arn', + ], + }, + unauthenticated: { + 'Fn::GetAtt': [ + 'TestIdentityPoolRoleMappingRulesUnauthenticatedRole79A7AF99', + 'Arn', + ], + }, + }, + }); + temp.hasResourceProperties('AWS::Cognito::IdentityPoolRoleAttachment', { + IdentityPoolId: { + Ref: 'TestIdentityPoolRoleMappingRulesC8C07BC3', + }, + RoleMappings: { + 'graph.facebook.com': { + AmbiguousRoleResolution: 'Deny', + IdentityProvider: 'graph.facebook.com', + RulesConfiguration: { + Rules: [ + { + Claim: 'iss', + MatchType: 'Equals', + RoleARN: { + 'Fn::GetAtt': [ + 'facebookRole9D649CD8', + 'Arn', + ], + }, + Value: 'https://graph.facebook.com', + }, + ], + }, + Type: 'Rules', + }, + 'example.com': { + AmbiguousRoleResolution: 'Deny', + IdentityProvider: 'example.com', + RulesConfiguration: { + Rules: [ + { + Claim: 'iss', + MatchType: 'Equals', + RoleARN: { + 'Fn::GetAtt': [ + 'customRole4C920FF0', + 'Arn', + ], + }, + Value: 'https://example.com', + }, + ], + }, + Type: 'Rules', + }, + }, + }); + }); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.expected.json b/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.expected.json new file mode 100644 index 0000000000000..b555de31baa1e --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.expected.json @@ -0,0 +1,417 @@ +{ + "Resources": { + "PoolD3F588B8": { + "Type": "AWS::Cognito::UserPool", + "Properties": { + "AccountRecoverySetting": { + "RecoveryMechanisms": [ + { + "Name": "verified_phone_number", + "Priority": 1 + }, + { + "Name": "verified_email", + "Priority": 2 + } + ] + }, + "AdminCreateUserConfig": { + "AllowAdminCreateUserOnly": true + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "VerificationMessageTemplate": { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "PoolUserPoolAuthenticationProviderClient20F2FFC4": { + "Type": "AWS::Cognito::UserPoolClient", + "Properties": { + "UserPoolId": { + "Ref": "PoolD3F588B8" + }, + "AllowedOAuthFlows": [ + "implicit", + "code" + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin" + ], + "CallbackURLs": [ + "https://example.com" + ], + "SupportedIdentityProviders": [ + { + "Ref": "PoolProviderGoogle76A1E8D0" + }, + "COGNITO" + ] + } + }, + "PoolProviderGoogle76A1E8D0": { + "Type": "AWS::Cognito::UserPoolIdentityProvider", + "Properties": { + "ProviderName": "Google", + "ProviderType": "Google", + "UserPoolId": { + "Ref": "PoolD3F588B8" + }, + "AttributeMapping": { + "given_name": "given_name", + "family_name": "family_name", + "email": "email", + "gender": "gender", + "names": "names" + }, + "ProviderDetails": { + "client_id": "google-client-id", + "client_secret": "google-client-secret", + "authorize_scopes": "profile" + } + } + }, + "OtherPool7DA7F2F7": { + "Type": "AWS::Cognito::UserPool", + "Properties": { + "AccountRecoverySetting": { + "RecoveryMechanisms": [ + { + "Name": "verified_phone_number", + "Priority": 1 + }, + { + "Name": "verified_email", + "Priority": 2 + } + ] + }, + "AdminCreateUserConfig": { + "AllowAdminCreateUserOnly": true + }, + "EmailVerificationMessage": "The verification code to your new account is {####}", + "EmailVerificationSubject": "Verify your new account", + "SmsVerificationMessage": "The verification code to your new account is {####}", + "VerificationMessageTemplate": { + "DefaultEmailOption": "CONFIRM_WITH_CODE", + "EmailMessage": "The verification code to your new account is {####}", + "EmailSubject": "Verify your new account", + "SmsMessage": "The verification code to your new account is {####}" + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "OtherPoolUserPoolAuthenticationProviderClient08F670F8": { + "Type": "AWS::Cognito::UserPoolClient", + "Properties": { + "UserPoolId": { + "Ref": "OtherPool7DA7F2F7" + }, + "AllowedOAuthFlows": [ + "implicit", + "code" + ], + "AllowedOAuthFlowsUserPoolClient": true, + "AllowedOAuthScopes": [ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin" + ], + "CallbackURLs": [ + "https://example.com" + ], + "SupportedIdentityProviders": [ + { + "Ref": "OtherPoolProviderAmazon4EB0592F" + }, + "COGNITO" + ] + } + }, + "OtherPoolProviderAmazon4EB0592F": { + "Type": "AWS::Cognito::UserPoolIdentityProvider", + "Properties": { + "ProviderName": "LoginWithAmazon", + "ProviderType": "LoginWithAmazon", + "UserPoolId": { + "Ref": "OtherPool7DA7F2F7" + }, + "AttributeMapping": { + "given_name": "name", + "email": "email", + "userId": "user_id" + }, + "ProviderDetails": { + "client_id": "amzn-client-id", + "client_secret": "amzn-client-secret", + "authorize_scopes": "profile" + } + } + }, + "identitypoolE2A6D099": { + "Type": "AWS::Cognito::IdentityPool", + "Properties": { + "AllowUnauthenticatedIdentities": false, + "AllowClassicFlow": true, + "CognitoIdentityProviders": [ + { + "ClientId": { + "Ref": "PoolUserPoolAuthenticationProviderClient20F2FFC4" + }, + "ProviderName": { + "Fn::Join": [ + "", + [ + "cognito-idp.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Ref": "PoolD3F588B8" + } + ] + ] + }, + "ServerSideTokenCheck": true + }, + { + "ClientId": { + "Ref": "OtherPoolUserPoolAuthenticationProviderClient08F670F8" + }, + "ProviderName": { + "Fn::Join": [ + "", + [ + "cognito-idp.", + { + "Ref": "AWS::Region" + }, + ".", + { + "Ref": "AWS::URLSuffix" + }, + "/", + { + "Ref": "OtherPool7DA7F2F7" + } + ] + ] + }, + "ServerSideTokenCheck": true + } + ], + "IdentityPoolName": "my-id-pool", + "SupportedLoginProviders": { + "www.amazon.com": "amzn1.application.12312k3j234j13rjiwuenf", + "accounts.google.com": "12345678012.apps.googleusercontent.com" + } + }, + "DependsOn": [ + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + }, + "identitypoolAuthenticatedRoleB074B49D": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "cognito-identity.amazonaws.com:aud": { + "Ref": "identitypoolE2A6D099" + } + }, + "ForAnyValue:StringLike": { + "cognito-identity.amazonaws.com:amr": "authenticated" + } + }, + "Effect": "Allow", + "Principal": { + "Federated": "cognito-identity.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Description": { + "Fn::Join": [ + "", + [ + "Default Authenticated Role for Identity Pool ", + { + "Fn::GetAtt": [ + "identitypoolE2A6D099", + "Name" + ] + } + ] + ] + } + }, + "DependsOn": [ + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + }, + "identitypoolAuthenticatedRoleDefaultPolicyCB4D2992": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "identitypoolAuthenticatedRoleDefaultPolicyCB4D2992", + "Roles": [ + { + "Ref": "identitypoolAuthenticatedRoleB074B49D" + } + ] + }, + "DependsOn": [ + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + }, + "identitypoolUnauthenticatedRoleE61CAC70": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "cognito-identity.amazonaws.com:aud": { + "Ref": "identitypoolE2A6D099" + } + }, + "ForAnyValue:StringLike": { + "cognito-identity.amazonaws.com:amr": "unauthenticated" + } + }, + "Effect": "Allow", + "Principal": { + "Federated": "cognito-identity.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Description": { + "Fn::Join": [ + "", + [ + "Default Unauthenticated Role for Identity Pool ", + { + "Fn::GetAtt": [ + "identitypoolE2A6D099", + "Name" + ] + } + ] + ] + } + }, + "DependsOn": [ + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + }, + "identitypoolUnauthenticatedRoleDefaultPolicyBFACCE98": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:Get*", + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "identitypoolUnauthenticatedRoleDefaultPolicyBFACCE98", + "Roles": [ + { + "Ref": "identitypoolUnauthenticatedRoleE61CAC70" + } + ] + }, + "DependsOn": [ + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + }, + "identitypoolDefaultRoleAttachment6BCAB114": { + "Type": "AWS::Cognito::IdentityPoolRoleAttachment", + "Properties": { + "IdentityPoolId": { + "Ref": "identitypoolE2A6D099" + }, + "Roles": { + "authenticated": { + "Fn::GetAtt": [ + "identitypoolAuthenticatedRoleB074B49D", + "Arn" + ] + }, + "unauthenticated": { + "Fn::GetAtt": [ + "identitypoolUnauthenticatedRoleE61CAC70", + "Arn" + ] + } + } + }, + "DependsOn": [ + "identitypoolAuthenticatedRoleDefaultPolicyCB4D2992", + "identitypoolAuthenticatedRoleB074B49D", + "identitypoolE2A6D099", + "identitypoolUnauthenticatedRoleDefaultPolicyBFACCE98", + "identitypoolUnauthenticatedRoleE61CAC70", + "OtherPool7DA7F2F7", + "OtherPoolUserPoolAuthenticationProviderClient08F670F8", + "PoolD3F588B8", + "PoolUserPoolAuthenticationProviderClient20F2FFC4" + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.ts b/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.ts new file mode 100644 index 0000000000000..5fc7ee1027084 --- /dev/null +++ b/packages/@aws-cdk/aws-cognito-identitypool/test/integ.identitypool.ts @@ -0,0 +1,73 @@ +import { + UserPool, + UserPoolIdentityProviderGoogle, + UserPoolIdentityProviderAmazon, + ProviderAttribute, +} from '@aws-cdk/aws-cognito'; +import { + Effect, + PolicyStatement, +} from '@aws-cdk/aws-iam'; +import { + App, + Stack, +} from '@aws-cdk/core'; +import { + IdentityPool, +} from '../lib/identitypool'; +import { + UserPoolAuthenticationProvider, +} from '../lib/identitypool-user-pool-authentication-provider'; + +const app = new App(); +const stack = new Stack(app, 'integ-identitypool'); + +const userPool = new UserPool(stack, 'Pool'); +new UserPoolIdentityProviderGoogle(stack, 'PoolProviderGoogle', { + userPool, + clientId: 'google-client-id', + clientSecret: 'google-client-secret', + attributeMapping: { + givenName: ProviderAttribute.GOOGLE_GIVEN_NAME, + familyName: ProviderAttribute.GOOGLE_FAMILY_NAME, + email: ProviderAttribute.GOOGLE_EMAIL, + gender: ProviderAttribute.GOOGLE_GENDER, + custom: { + names: ProviderAttribute.GOOGLE_NAMES, + }, + }, +}); +const otherPool = new UserPool(stack, 'OtherPool'); +new UserPoolIdentityProviderAmazon(stack, 'OtherPoolProviderAmazon', { + userPool: otherPool, + clientId: 'amzn-client-id', + clientSecret: 'amzn-client-secret', + attributeMapping: { + givenName: ProviderAttribute.AMAZON_NAME, + email: ProviderAttribute.AMAZON_EMAIL, + custom: { + userId: ProviderAttribute.AMAZON_USER_ID, + }, + }, +}); +const idPool = new IdentityPool(stack, 'identitypool', { + authenticationProviders: { + userPools: [new UserPoolAuthenticationProvider({ userPool })], + amazon: { appId: 'amzn1.application.12312k3j234j13rjiwuenf' }, + google: { clientId: '12345678012.apps.googleusercontent.com' }, + }, + allowClassicFlow: true, + identityPoolName: 'my-id-pool', +}); +idPool.authenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['dynamodb:*'], + resources: ['*'], +})); +idPool.unauthenticatedRole.addToPrincipalPolicy(new PolicyStatement({ + effect: Effect.ALLOW, + actions: ['dynamodb:Get*'], + resources: ['*'], +})); +idPool.addUserPoolAuthentication(new UserPoolAuthenticationProvider({ userPool: otherPool })); +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-cognito/README.md b/packages/@aws-cdk/aws-cognito/README.md index 2cb86ba2885dd..ef968f5151bd2 100644 --- a/packages/@aws-cdk/aws-cognito/README.md +++ b/packages/@aws-cdk/aws-cognito/README.md @@ -31,7 +31,7 @@ The two main components of Amazon Cognito are [user pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) and [identity pools](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html). User pools are user directories that provide sign-up and sign-in options for your app users. Identity pools enable you to grant your users access to -other AWS services. +other AWS services. Identity Pool L2 Constructs can be found [here](../aws-cognito-identitypool). 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/package.json b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json index 5dc4b913222bc..d9b2afa5c1fbd 100644 --- a/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json +++ b/packages/@aws-cdk/aws-dynamodb-global/lambda-packages/aws-global-table-coordinator/package.json @@ -39,6 +39,6 @@ "eslint-plugin-standard": "^4.1.0", "jest": "^27.4.7", "lambda-tester": "^3.6.0", - "nock": "^13.2.1" + "nock": "^13.2.2" } } diff --git a/packages/@aws-cdk/aws-dynamodb-global/package.json b/packages/@aws-cdk/aws-dynamodb-global/package.json index 88856d300eda9..61e2d44daab47 100644 --- a/packages/@aws-cdk/aws-dynamodb-global/package.json +++ b/packages/@aws-cdk/aws-dynamodb-global/package.json @@ -56,7 +56,7 @@ "constructs": "^3.3.69" }, "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", 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 index 5a6a45d5be3a3..1d6f90d4a16ad 100644 --- a/packages/@aws-cdk/aws-dynamodb-global/test/dynamodb-global.test.ts +++ b/packages/@aws-cdk/aws-dynamodb-global/test/dynamodb-global.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +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'; @@ -26,7 +26,7 @@ describeDeprecated('Default Global DynamoDB stack', () => { 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; - expect(tableStack).toHaveResource('AWS::DynamoDB::Table', { + Template.fromStack(tableStack).hasResourceProperties('AWS::DynamoDB::Table', { 'KeySchema': [ { 'AttributeName': 'hashKey', @@ -46,12 +46,12 @@ describeDeprecated('Default Global DynamoDB stack', () => { }); } const customResourceStack = stack.node.findChild(CONSTRUCT_NAME + '-CustomResource') as Stack; - expect(customResourceStack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(customResourceStack).hasResourceProperties('AWS::Lambda::Function', { Description: 'Lambda to make DynamoDB a global table', Handler: 'index.handler', Timeout: 300, }); - expect(customResourceStack).toHaveResource('AWS::CloudFormation::CustomResource', { + Template.fromStack(customResourceStack).hasResourceProperties('AWS::CloudFormation::CustomResource', { Regions: STACK_PROPS.regions, ResourceType: 'Custom::DynamoGlobalTableCoordinator', TableName: TABLE_NAME, @@ -75,7 +75,7 @@ testDeprecated('GlobalTable generated stacks inherit their account from the pare value: globalTable.regionalTables[0].tableStreamArn!, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Outputs': { 'DynamoDbOutput': { 'Value': { diff --git a/packages/@aws-cdk/aws-dynamodb/lib/scalable-table-attribute.ts b/packages/@aws-cdk/aws-dynamodb/lib/scalable-table-attribute.ts index fc2a538e2545d..8c5f6467f4715 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/scalable-table-attribute.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/scalable-table-attribute.ts @@ -25,7 +25,7 @@ export class ScalableTableAttribute extends appscaling.BaseScalableAttribute { } this.scalingPolicyCreated = true; const predefinedMetric = this.props.dimension.indexOf('ReadCapacity') === -1 - ? appscaling.PredefinedMetric.DYANMODB_WRITE_CAPACITY_UTILIZATION + ? appscaling.PredefinedMetric.DYNAMODB_WRITE_CAPACITY_UTILIZATION : appscaling.PredefinedMetric.DYNAMODB_READ_CAPACITY_UTILIZATION; super.doScaleToTrackMetric('Tracking', { diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md index 16c999efde724..c40b8e6879709 100644 --- a/packages/@aws-cdk/aws-ec2/README.md +++ b/packages/@aws-cdk/aws-ec2/README.md @@ -854,6 +854,46 @@ You can use the `Instance` class to start up a single EC2 instance. For producti you use an `AutoScalingGroup` from the `aws-autoscaling` module instead, as AutoScalingGroups will take care of restarting your instance if it ever fails. +```ts +declare const vpc: ec2.Vpc; +declare const instanceType: ec2.InstanceType; + +// AWS Linux +new ec2.Instance(this, 'Instance1', { + vpc, + instanceType, + machineImage: new ec2.AmazonLinuxImage(), +}); + +// AWS Linux 2 +new ec2.Instance(this, 'Instance2', { + vpc, + instanceType, + machineImage: new ec2.AmazonLinuxImage({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + }), +}); + +// AWS Linux 2 with kernel 5.x +new ec2.Instance(this, 'Instance3', { + vpc, + instanceType, + machineImage: new ec2.AmazonLinuxImage({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + kernel: ec2.AmazonLinuxKernel.KERNEL5_X, + }), +}); + +// AWS Linux 2022 +new ec2.Instance(this, 'Instance4', { + vpc, + instanceType, + machineImage: new ec2.AmazonLinuxImage({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2022, + }), +}); +``` + ### Configuring Instances using CloudFormation Init (cfn-init) CloudFormation Init allows you to configure your instances by writing files to them, installing software diff --git a/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts b/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts index f1a5270f1fb08..abad030c160a8 100644 --- a/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts +++ b/packages/@aws-cdk/aws-ec2/lib/aspects/require-imdsv2-aspect.ts @@ -1,4 +1,6 @@ import * as cdk from '@aws-cdk/core'; +import { FeatureFlags } from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; import { CfnLaunchTemplate } from '../ec2.generated'; import { Instance } from '../instance'; import { LaunchTemplate } from '../launch-template'; @@ -83,17 +85,20 @@ export class InstanceRequireImdsv2Aspect extends RequireImdsv2Aspect { return; } - const name = `${node.node.id}LaunchTemplate`; const launchTemplate = new CfnLaunchTemplate(node, 'LaunchTemplate', { launchTemplateData: { metadataOptions: { httpTokens: 'required', }, }, - launchTemplateName: name, }); + if (FeatureFlags.of(node).isEnabled(cxapi.EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME)) { + launchTemplate.launchTemplateName = cdk.Names.uniqueId(launchTemplate); + } else { + launchTemplate.launchTemplateName = `${node.node.id}LaunchTemplate`; + } node.instance.launchTemplate = { - launchTemplateName: name, + launchTemplateName: launchTemplate.launchTemplateName, version: launchTemplate.getAtt('LatestVersionNumber').toString(), }; } diff --git a/packages/@aws-cdk/aws-ec2/lib/machine-image.ts b/packages/@aws-cdk/aws-ec2/lib/machine-image.ts index 731d9ea8d0c43..789d17c5167bd 100644 --- a/packages/@aws-cdk/aws-ec2/lib/machine-image.ts +++ b/packages/@aws-cdk/aws-ec2/lib/machine-image.ts @@ -309,6 +309,13 @@ export interface AmazonLinuxImageProps { */ readonly edition?: AmazonLinuxEdition; + /** + * What kernel version of Amazon Linux to use + * + * @default - + */ + readonly kernel?: AmazonLinuxKernel; + /** * Virtualization type * @@ -376,13 +383,29 @@ export class AmazonLinuxImage extends GenericSSMParameterImage { public static ssmParameterName(props: AmazonLinuxImageProps = {}) { const generation = (props && props.generation) || AmazonLinuxGeneration.AMAZON_LINUX; const edition = (props && props.edition) || AmazonLinuxEdition.STANDARD; - const virtualization = (props && props.virtualization) || AmazonLinuxVirt.HVM; - const storage = (props && props.storage) || AmazonLinuxStorage.GENERAL_PURPOSE; const cpu = (props && props.cpuType) || AmazonLinuxCpuType.X86_64; + let kernel = (props && props.kernel) || undefined; + let virtualization: AmazonLinuxVirt | undefined; + let storage: AmazonLinuxStorage | undefined; + + if (generation === AmazonLinuxGeneration.AMAZON_LINUX_2022) { + kernel = AmazonLinuxKernel.KERNEL5_X; + if (props && props.storage) { + throw new Error('Storage parameter does not exist in smm parameter name for Amazon Linux 2022.'); + } + if (props && props.virtualization) { + throw new Error('Virtualization parameter does not exist in smm parameter name for Amazon Linux 2022.'); + } + } else { + virtualization = (props && props.virtualization) || AmazonLinuxVirt.HVM; + storage = (props && props.storage) || AmazonLinuxStorage.GENERAL_PURPOSE; + } + const parts: Array = [ generation, 'ami', edition !== AmazonLinuxEdition.STANDARD ? edition : undefined, + kernel, virtualization, cpu, storage, @@ -427,6 +450,21 @@ export enum AmazonLinuxGeneration { * Amazon Linux 2 */ AMAZON_LINUX_2 = 'amzn2', + + /** + * Amazon Linux 2022 + */ + AMAZON_LINUX_2022 = 'al2022', +} + +/** + * Amazon Linux Kernel + */ +export enum AmazonLinuxKernel { + /** + * Standard edition + */ + KERNEL5_X = 'kernel-5.10', } /** @@ -441,7 +479,7 @@ export enum AmazonLinuxEdition { /** * Minimal edition */ - MINIMAL = 'minimal' + MINIMAL = 'minimal', } /** @@ -456,7 +494,7 @@ export enum AmazonLinuxVirt { /** * PV virtualization */ - PV = 'pv' + PV = 'pv', } export enum AmazonLinuxStorage { @@ -468,7 +506,7 @@ export enum AmazonLinuxStorage { /** * S3-backed storage */ - S3 = 'ebs', + S3 = 's3', /** * General Purpose-based storage (recommended) diff --git a/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts b/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts index ade2eaeab1f1d..189244bc251f5 100644 --- a/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/aspects/require-imdsv2-aspect.test.ts @@ -4,7 +4,9 @@ import { haveResourceLike, } from '@aws-cdk/assert-internal'; import '@aws-cdk/assert-internal/jest'; +import { testFutureBehavior, testLegacyBehavior } from '@aws-cdk/cdk-build-tools'; import * as cdk from '@aws-cdk/core'; +import * as cxapi from '@aws-cdk/cx-api'; import { CfnLaunchTemplate, Instance, @@ -135,6 +137,57 @@ describe('RequireImdsv2Aspect', () => { trace: undefined, }); }); + + testFutureBehavior('launch template name is unique with feature flag', { [cxapi.EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME]: true }, cdk.App, (app2) => { + // GIVEN + const otherStack = new cdk.Stack(app2, 'OtherStack'); + const otherVpc = new Vpc(otherStack, 'OtherVpc'); + const otherInstance = new Instance(otherStack, 'OtherInstance', { + vpc: otherVpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + const imdsv2Stack = new cdk.Stack(app2, 'RequireImdsv2Stack'); + const imdsv2Vpc = new Vpc(imdsv2Stack, 'Vpc'); + const instance = new Instance(imdsv2Stack, 'Instance', { + vpc: imdsv2Vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + const aspect = new InstanceRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(imdsv2Stack).add(aspect); + cdk.Aspects.of(otherStack).add(aspect); + app2.synth(); + + // THEN + const launchTemplate = instance.node.tryFindChild('LaunchTemplate') as LaunchTemplate; + const otherLaunchTemplate = otherInstance.node.tryFindChild('LaunchTemplate') as LaunchTemplate; + expect(launchTemplate).toBeDefined(); + expect(otherLaunchTemplate).toBeDefined(); + expect(launchTemplate.launchTemplateName !== otherLaunchTemplate.launchTemplateName); + }); + + testLegacyBehavior('launch template name uses legacy id without feature flag', cdk.App, (app2) => { + // GIVEN + const imdsv2Stack = new cdk.Stack(app2, 'RequireImdsv2Stack'); + const imdsv2Vpc = new Vpc(imdsv2Stack, 'Vpc'); + const instance = new Instance(imdsv2Stack, 'Instance', { + vpc: imdsv2Vpc, + instanceType: new InstanceType('t2.micro'), + machineImage: MachineImage.latestAmazonLinux(), + }); + const aspect = new InstanceRequireImdsv2Aspect(); + + // WHEN + cdk.Aspects.of(imdsv2Stack).add(aspect); + app2.synth(); + + // THEN + const launchTemplate = instance.node.tryFindChild('LaunchTemplate') as LaunchTemplate; + expect(launchTemplate.launchTemplateName).toEqual(`${instance.node.id}LaunchTemplate`); + }); }); describe('LaunchTemplateRequireImdsv2Aspect', () => { diff --git a/packages/@aws-cdk/aws-ec2/test/example.images.lit.ts b/packages/@aws-cdk/aws-ec2/test/example.images.lit.ts index 4fbff22fb86a4..2092e0d2fd87b 100644 --- a/packages/@aws-cdk/aws-ec2/test/example.images.lit.ts +++ b/packages/@aws-cdk/aws-ec2/test/example.images.lit.ts @@ -15,7 +15,7 @@ const amznLinux = ec2.MachineImage.latestAmazonLinux({ const windows = ec2.MachineImage.latestWindows(ec2.WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE); // Read AMI id from SSM parameter store -const ssm = ec2.MachineImage.fromSSMParameter('/my/ami', ec2.OperatingSystemType.LINUX); +const ssm = ec2.MachineImage.fromSsmParameter('/my/ami', { os: ec2.OperatingSystemType.LINUX }); // Look up the most recent image matching a set of AMI filters. // In this case, look up the NAT instance AMI, by using a wildcard diff --git a/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts b/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts index a25acdfbb4cfa..39263075fdb21 100644 --- a/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/machine-image.test.ts @@ -177,6 +177,93 @@ test('cached lookups of Amazon Linux', () => { ]); }); +test('cached lookups of Amazon Linux 2', () => { + // WHEN + const ami = ec2.MachineImage.latestAmazonLinux({ + cachedInContext: true, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + }).getImage(stack).imageId; + + // THEN + expect(ami).toEqual('dummy-value-for-/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'); + expect(app.synth().manifest.missing).toEqual([ + { + key: 'ssm:account=1234:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2:region=testregion', + props: { + account: '1234', + region: 'testregion', + parameterName: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2', + }, + provider: 'ssm', + }, + ]); +}); + +test('cached lookups of Amazon Linux 2 with kernel 5.x', () => { + // WHEN + const ami = ec2.MachineImage.latestAmazonLinux({ + cachedInContext: true, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + kernel: ec2.AmazonLinuxKernel.KERNEL5_X, + }).getImage(stack).imageId; + + // THEN + expect(ami).toEqual('dummy-value-for-/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2'); + expect(app.synth().manifest.missing).toEqual([ + { + key: 'ssm:account=1234:parameterName=/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2:region=testregion', + props: { + account: '1234', + region: 'testregion', + parameterName: '/aws/service/ami-amazon-linux-latest/amzn2-ami-kernel-5.10-hvm-x86_64-gp2', + }, + provider: 'ssm', + }, + ]); +}); + +test('throw error if storage param is set for Amazon Linux 2022', () => { + expect(() => { + ec2.MachineImage.latestAmazonLinux({ + cachedInContext: true, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2022, + storage: ec2.AmazonLinuxStorage.GENERAL_PURPOSE, + }).getImage(stack).imageId; + }).toThrow(/Storage parameter does not exist in smm parameter name for Amazon Linux 2022./); +}); + +test('throw error if virtualization param is set for Amazon Linux 2022', () => { + expect(() => { + ec2.MachineImage.latestAmazonLinux({ + cachedInContext: true, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2022, + virtualization: ec2.AmazonLinuxVirt.HVM, + }).getImage(stack).imageId; + }).toThrow(/Virtualization parameter does not exist in smm parameter name for Amazon Linux 2022./); +}); + +test('cached lookups of Amazon Linux 2022 with kernel 5.x', () => { + // WHEN + const ami = ec2.MachineImage.latestAmazonLinux({ + cachedInContext: true, + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2022, + }).getImage(stack).imageId; + + // THEN + expect(ami).toEqual('dummy-value-for-/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-5.10-x86_64'); + expect(app.synth().manifest.missing).toEqual([ + { + key: 'ssm:account=1234:parameterName=/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-5.10-x86_64:region=testregion', + props: { + account: '1234', + region: 'testregion', + parameterName: '/aws/service/ami-amazon-linux-latest/al2022-ami-kernel-5.10-x86_64', + }, + provider: 'ssm', + }, + ]); +}); + function isWindowsUserData(ud: ec2.UserData) { return ud.render().indexOf('powershell') > -1; } diff --git a/packages/@aws-cdk/aws-ecs/lib/log-drivers/aws-log-driver.ts b/packages/@aws-cdk/aws-ecs/lib/log-drivers/aws-log-driver.ts index e6da02b29797e..2bca7326e18f3 100644 --- a/packages/@aws-cdk/aws-ecs/lib/log-drivers/aws-log-driver.ts +++ b/packages/@aws-cdk/aws-ecs/lib/log-drivers/aws-log-driver.ts @@ -1,5 +1,4 @@ import * as logs from '@aws-cdk/aws-logs'; -import { Stack } from '@aws-cdk/core'; import { ContainerDefinition } from '../container-definition'; import { LogDriver, LogDriverConfig } from './log-driver'; import { removeEmpty } from './utils'; @@ -127,7 +126,7 @@ export class AwsLogDriver extends LogDriver { options: removeEmpty({ 'awslogs-group': this.logGroup.logGroupName, 'awslogs-stream-prefix': this.props.streamPrefix, - 'awslogs-region': Stack.of(containerDefinition).region, + 'awslogs-region': this.logGroup.env.region, 'awslogs-datetime-format': this.props.datetimeFormat, 'awslogs-multiline-pattern': this.props.multilinePattern, 'mode': this.props.mode, diff --git a/packages/@aws-cdk/aws-ecs/package.json b/packages/@aws-cdk/aws-ecs/package.json index 4dd48f968fcf3..c3d3def173a2b 100644 --- a/packages/@aws-cdk/aws-ecs/package.json +++ b/packages/@aws-cdk/aws-ecs/package.json @@ -79,7 +79,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-s3-deployment": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-ecs/test/app-mesh-proxy-configuration.test.ts b/packages/@aws-cdk/aws-ecs/test/app-mesh-proxy-configuration.test.ts index 7c8bd5f880f77..683a7301b54dd 100644 --- a/packages/@aws-cdk/aws-ecs/test/app-mesh-proxy-configuration.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/app-mesh-proxy-configuration.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -33,7 +33,7 @@ describe('app mesh proxy configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ProxyConfiguration: { ContainerName: 'envoy', ProxyConfigurationProperties: [ @@ -99,7 +99,7 @@ describe('app mesh proxy configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ProxyConfiguration: { ContainerName: 'envoy', ProxyConfigurationProperties: [ @@ -155,7 +155,7 @@ describe('app mesh proxy configuration', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ProxyConfiguration: { ContainerName: 'envoy', ProxyConfigurationProperties: [ diff --git a/packages/@aws-cdk/aws-ecs/test/aws-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/aws-log-driver.test.ts index 5e570a7d39eeb..de7e4faa24f19 100644 --- a/packages/@aws-cdk/aws-ecs/test/aws-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/aws-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -29,13 +29,13 @@ describe('aws log driver', () => { }); // THEN - expect(stack).toHaveResource('AWS::Logs::LogGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { RetentionInDays: logs.RetentionDays.ONE_MONTH, }); - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awslogs', Options: { @@ -47,11 +47,9 @@ describe('aws log driver', () => { 'mode': 'non-blocking', }, }, - }, + }), ], }); - - }); test('create an aws log driver using awsLogs', () => { @@ -67,13 +65,13 @@ describe('aws log driver', () => { }); // THEN - expect(stack).toHaveResource('AWS::Logs::LogGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { RetentionInDays: logs.RetentionDays.ONE_MONTH, }); - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awslogs', Options: { @@ -84,11 +82,9 @@ describe('aws log driver', () => { 'awslogs-multiline-pattern': 'pattern', }, }, - }, + }), ], }); - - }); test('with a defined log group', () => { @@ -105,13 +101,13 @@ describe('aws log driver', () => { }); // THEN - expect(stack).toHaveResource('AWS::Logs::LogGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', { RetentionInDays: logs.RetentionDays.TWO_YEARS, }); - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awslogs', Options: { @@ -120,11 +116,9 @@ describe('aws log driver', () => { 'awslogs-region': { Ref: 'AWS::Region' }, }, }, - }, + }), ], }); - - }); test('without a defined log group: creates one anyway', () => { @@ -137,9 +131,7 @@ describe('aws log driver', () => { }); // THEN - expect(stack).toHaveResource('AWS::Logs::LogGroup', {}); - - + Template.fromStack(stack).hasResourceProperties('AWS::Logs::LogGroup', {}); }); test('throws when specifying log retention and log group', () => { @@ -155,4 +147,37 @@ describe('aws log driver', () => { }); + + test('allows cross-region log group', () => { + // GIVEN + const logGroupRegion = 'asghard'; + const logGroup = logs.LogGroup.fromLogGroupArn(stack, 'LogGroup', + `arn:aws:logs:${logGroupRegion}:1234:log-group:my_log_group`); + + // WHEN + td.addContainer('Container', { + image, + logging: new ecs.AwsLogDriver({ + logGroup, + streamPrefix: 'hello', + }), + }); + + // THEN + Template.fromStack(stack).resourceCountIs('AWS::Logs::LogGroup', 0); + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + Match.objectLike({ + LogConfiguration: { + LogDriver: 'awslogs', + Options: { + 'awslogs-group': logGroup.logGroupName, + 'awslogs-stream-prefix': 'hello', + 'awslogs-region': logGroupRegion, + }, + }, + }), + ], + }); + }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts index 15a25f6987559..f6b34f76439c0 100644 --- a/packages/@aws-cdk/aws-ecs/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/cluster.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as autoscaling from '@aws-cdk/aws-autoscaling'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as kms from '@aws-cdk/aws-kms'; @@ -21,9 +20,9 @@ describe('cluster', () => { instanceType: new ec2.InstanceType('t2.micro'), }); - expect(stack).toHaveResource('AWS::ECS::Cluster'); + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); - expect(stack).toHaveResource('AWS::EC2::VPC', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPC', { CidrBlock: '10.0.0.0/16', EnableDnsHostnames: true, EnableDnsSupport: true, @@ -36,7 +35,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -69,7 +68,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '1', MinSize: '1', LaunchConfigurationName: { @@ -92,7 +91,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Default/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup', SecurityGroupEgress: [ { @@ -112,7 +111,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -127,7 +126,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -192,9 +191,9 @@ describe('cluster', () => { instanceType: new ec2.InstanceType('t2.micro'), }); - expect(stack).toHaveResource('AWS::ECS::Cluster'); + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); - expect(stack).toHaveResource('AWS::EC2::VPC', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPC', { CidrBlock: '10.0.0.0/16', EnableDnsHostnames: true, EnableDnsSupport: true, @@ -207,7 +206,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -240,7 +239,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '1', MinSize: '1', LaunchConfigurationName: { @@ -263,7 +262,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Default/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup', SecurityGroupEgress: [ { @@ -283,7 +282,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -298,7 +297,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -381,7 +380,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LifecycleHook', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LifecycleHook', { AutoScalingGroupName: { Ref: 'EcsClusterDefaultAutoScalingGroupASGC1A785DB' }, LifecycleTransition: 'autoscaling:EC2_INSTANCE_TERMINATING', DefaultResult: 'CONTINUE', @@ -390,7 +389,7 @@ describe('cluster', () => { RoleARN: { 'Fn::GetAtt': ['EcsClusterDefaultAutoScalingGroupLifecycleHookDrainHookRoleA38EC83B', 'Arn'] }, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Timeout: 310, Environment: { Variables: { @@ -402,7 +401,7 @@ describe('cluster', () => { Handler: 'index.lambda_handler', }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -522,7 +521,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::SNS::Topic', { + Template.fromStack(stack).hasResourceProperties('AWS::SNS::Topic', { KmsMasterKeyId: { 'Fn::GetAtt': [ 'Key961B73FD', @@ -549,16 +548,16 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::PrivateDnsNamespace', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::PrivateDnsNamespace', { Name: 'foo.com', Vpc: { Ref: 'MyVpcF9F0CA6F', }, }); - expect(stack).toHaveResource('AWS::ECS::Cluster'); + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); - expect(stack).toHaveResource('AWS::EC2::VPC', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPC', { CidrBlock: '10.0.0.0/16', EnableDnsHostnames: true, EnableDnsSupport: true, @@ -571,7 +570,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -604,7 +603,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '1', MinSize: '1', LaunchConfigurationName: { @@ -627,7 +626,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Default/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup', SecurityGroupEgress: [ { @@ -647,7 +646,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -662,7 +661,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -727,7 +726,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { InstanceType: 'm3.large', }); @@ -746,7 +745,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '3', }); @@ -767,7 +766,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiwindowsserver2019englishfullrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -826,7 +825,7 @@ describe('cluster', () => { // THEN const assembly = app.synth(); const template = assembly.getStackByName(stack.stackName).template; - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1028,7 +1027,7 @@ describe('cluster', () => { // THEN const assembly = app.synth(); const template = assembly.getStackByName(stack.stackName).template; - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2gpurecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1059,7 +1058,7 @@ describe('cluster', () => { // THEN const assembly = app.synth(); const template = assembly.getStackByName(stack.stackName).template; - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinuxrecommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1112,7 +1111,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { SpotPrice: '0.31', }); @@ -1131,7 +1130,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LifecycleHook', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LifecycleHook', { HeartbeatTimeout: 60, }); @@ -1151,7 +1150,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { UserData: { 'Fn::Base64': { 'Fn::Join': [ @@ -1183,7 +1182,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { UserData: { 'Fn::Base64': { 'Fn::Join': [ @@ -1219,7 +1218,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::PrivateDnsNamespace', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::PrivateDnsNamespace', { Name: 'foo.com', Vpc: { Ref: 'MyVpcF9F0CA6F', @@ -1246,7 +1245,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::PublicDnsNamespace', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::PublicDnsNamespace', { Name: 'foo.com', }); @@ -1331,11 +1330,11 @@ describe('cluster', () => { cluster.connections.allowToAnyIpv4(ec2.Port.tcp(443)); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { GroupId: 'sg-1', }); - expect(stack).toCountResources('AWS::EC2::SecurityGroupEgress', 1); + Template.fromStack(stack).resourceCountIs('AWS::EC2::SecurityGroupEgress', 1); }); @@ -1403,9 +1402,9 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::ECS::Cluster'); + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); - expect(stack).toHaveResource('AWS::EC2::VPC', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::VPC', { CidrBlock: '10.0.0.0/16', EnableDnsHostnames: true, EnableDnsSupport: true, @@ -1418,7 +1417,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1452,7 +1451,7 @@ describe('cluster', () => { }, }); - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { MaxSize: '1', MinSize: '1', LaunchConfigurationName: { @@ -1475,7 +1474,7 @@ describe('cluster', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Default/EcsCluster/DefaultAutoScalingGroup/InstanceSecurityGroup', SecurityGroupEgress: [ { @@ -1507,7 +1506,7 @@ describe('cluster', () => { new ecs.Cluster(stack, 'EcsCluster', { containerInsights: true }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { ClusterSettings: [ { Name: 'containerInsights', @@ -1527,7 +1526,7 @@ describe('cluster', () => { new ecs.Cluster(stack, 'EcsCluster', { containerInsights: false }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { ClusterSettings: [ { Name: 'containerInsights', @@ -1593,9 +1592,9 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster'); - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup'); - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).resourceCountIs('AWS::ECS::Cluster', 1); + Template.fromStack(stack).resourceCountIs('AWS::AutoScaling::AutoScalingGroup', 1); + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsservicebottlerocketawsecs1x8664latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1614,7 +1613,7 @@ describe('cluster', () => { }, }, }); - expect(stack).toHaveResourceLike('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -1685,7 +1684,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsservicebottlerocketawsecs1arm64latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -1714,7 +1713,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { UserData: { 'Fn::Base64': { 'Fn::Join': [ @@ -1742,11 +1741,11 @@ describe('cluster', () => { new ecs.Cluster(stack, 'EcsCluster', { capacityProviders: ['FARGATE_SPOT'] }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE_SPOT'], }); @@ -1764,11 +1763,11 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE', 'FARGATE_SPOT'], }); @@ -1785,11 +1784,11 @@ describe('cluster', () => { cluster.enableFargateCapacityProviders(); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE', 'FARGATE_SPOT'], }); @@ -1807,11 +1806,11 @@ describe('cluster', () => { cluster.addCapacityProvider('FARGATE'); // does not add twice // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE'], }); @@ -1829,11 +1828,11 @@ describe('cluster', () => { cluster.addCapacityProvider('FARGATE'); // does not add twice // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE'], }); @@ -1871,7 +1870,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::CapacityProvider', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::CapacityProvider', { AutoScalingGroupProvider: { AutoScalingGroupArn: { Ref: 'asgASG4D014670', @@ -1904,12 +1903,12 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::CapacityProvider', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::CapacityProvider', { AutoScalingGroupProvider: { AutoScalingGroupArn: { Ref: 'asgASG4D014670', }, - ManagedScaling: ABSENT, + ManagedScaling: Match.absent(), ManagedTerminationProtection: 'ENABLED', }, }); @@ -1933,7 +1932,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::AutoScaling::AutoScalingGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { NewInstancesProtectedFromScaleIn: true, }); @@ -1957,10 +1956,9 @@ describe('cluster', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::AutoScaling::AutoScalingGroup', { - NewInstancesProtectedFromScaleIn: true, + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::AutoScalingGroup', { + NewInstancesProtectedFromScaleIn: Match.absent(), }); - }); test('can add ASG capacity via Capacity Provider', () => { @@ -1989,7 +1987,7 @@ describe('cluster', () => { cluster.addAsgCapacityProvider(capacityProvider); // THEN - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { Cluster: { Ref: 'EcsCluster97242B84', }, @@ -2036,7 +2034,7 @@ describe('cluster', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { Configuration: { ExecuteCommandConfiguration: { KmsKeyId: { @@ -2186,7 +2184,7 @@ test('can add ASG capacity via Capacity Provider by not specifying machineImageT // THEN Bottlerocket LaunchConfiguration - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsservicebottlerocketawsecs1x8664latestimageidC96584B6F00A464EAD1953AFF4B05118Parameter', @@ -2208,7 +2206,7 @@ test('can add ASG capacity via Capacity Provider by not specifying machineImageT }); // THEN AmazonLinux2 LaunchConfiguration - expect(stack).toHaveResource('AWS::AutoScaling::LaunchConfiguration', { + Template.fromStack(stack).hasResourceProperties('AWS::AutoScaling::LaunchConfiguration', { ImageId: { Ref: 'SsmParameterValueawsserviceecsoptimizedamiamazonlinux2recommendedimageidC96584B6F00A464EAD1953AFF4B05118Parameter', }, @@ -2229,7 +2227,7 @@ test('can add ASG capacity via Capacity Provider by not specifying machineImageT }, }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: [ 'FARGATE', 'FARGATE_SPOT', 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 ac7a7a7824450..47ee57b4625d6 100644 --- a/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/container-definition.test.ts @@ -1,6 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; -import { InspectionFailure } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as ecr_assets from '@aws-cdk/aws-ecr-assets'; import * as s3 from '@aws-cdk/aws-s3'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; @@ -24,7 +23,7 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Essential: true, @@ -91,7 +90,7 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Command: [ @@ -491,16 +490,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', (props: any, inspection: InspectionFailure) => { - if (props.NetworkMode === undefined) { - return true; - } - - inspection.failureReason = 'CF template should not have NetworkMode defined for a task definition that relies on NAT network mode.'; - return false; + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + NetworkMode: Match.absent(), }); - - }); }); }); @@ -700,9 +692,9 @@ describe('container definition', () => { container.addEnvironment('SECOND_ENVIRONEMENT_VARIABLE', 'second test value'); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Environment: [{ Name: 'TEST_ENVIRONMENT_VARIABLE', Value: 'test environment variable value', @@ -711,11 +703,9 @@ describe('container definition', () => { Name: 'SECOND_ENVIRONEMENT_VARIABLE', Value: 'second test value', }], - }, + }), ], }); - - }); test('can add environment variables to container definition with no environment', () => { @@ -731,18 +721,16 @@ describe('container definition', () => { container.addEnvironment('SECOND_ENVIRONEMENT_VARIABLE', 'second test value'); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Environment: [{ Name: 'SECOND_ENVIRONEMENT_VARIABLE', Value: 'second test value', }], - }, + }), ], }); - - }); test('can add port mappings to the container definition by props', () => { @@ -758,11 +746,11 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { - PortMappings: [{ ContainerPort: 80 }], - }, + Match.objectLike({ + PortMappings: [Match.objectLike({ ContainerPort: 80 })], + }), ], }); }); @@ -782,14 +770,14 @@ describe('container definition', () => { containerDefinition.addPortMappings({ containerPort: 443 }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ PortMappings: [ - { ContainerPort: 80 }, - { ContainerPort: 443 }, + Match.objectLike({ ContainerPort: 80 }), + Match.objectLike({ ContainerPort: 443 }), ], - }, + }), ], }); }); @@ -810,9 +798,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ SystemControls: [ { Namespace: 'SomeNamespace1', @@ -823,7 +811,7 @@ describe('container definition', () => { Value: 'SomeValue2', }, ], - }, + }), ], }); }); @@ -843,9 +831,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ EnvironmentFiles: [{ Type: 's3', Value: { @@ -887,11 +875,10 @@ describe('container definition', () => { ], }, }], - }, + }), ], }); - }); test('can add s3 bucket environment file to the container definition', () => { // GIVEN @@ -909,9 +896,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ EnvironmentFiles: [{ Type: 's3', Value: { @@ -927,13 +914,12 @@ describe('container definition', () => { ], }, }], - }, + }), ], }); - - }); }); + describe('with Fargate task definitions', () => { test('can add asset environment file to the container definition', () => { // GIVEN @@ -948,9 +934,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ EnvironmentFiles: [{ Type: 's3', Value: { @@ -992,12 +978,11 @@ describe('container definition', () => { ], }, }], - }, + }), ], }); - - }); + test('can add s3 bucket environment file to the container definition', () => { // GIVEN const stack = new cdk.Stack(); @@ -1014,9 +999,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ EnvironmentFiles: [{ Type: 's3', Value: { @@ -1032,11 +1017,9 @@ describe('container definition', () => { ], }, }], - }, + }), ], }); - - }); }); }); @@ -1055,9 +1038,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', ResourceRequirements: [ { @@ -1065,11 +1048,9 @@ describe('container definition', () => { Value: '4', }, ], - }, + }), ], }); - - }); }); @@ -1097,14 +1078,14 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', InferenceAccelerators: [{ DeviceName: 'device1', DeviceType: 'eia2.medium', }], ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', ResourceRequirements: [ { @@ -1112,12 +1093,11 @@ describe('container definition', () => { Value: 'device1', }, ], - }, + }), ], }); - - }); + test('correctly adds resource requirements to container definition using both props and addInferenceAcceleratorResource method', () => { // GIVEN const stack = new cdk.Stack(); @@ -1146,7 +1126,7 @@ describe('container definition', () => { container.addInferenceAcceleratorResource('device2'); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', InferenceAccelerators: [{ DeviceName: 'device1', @@ -1156,7 +1136,7 @@ describe('container definition', () => { DeviceType: 'eia2.large', }], ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', ResourceRequirements: [ { @@ -1168,11 +1148,11 @@ describe('container definition', () => { Value: 'device2', }, ], - }, + }), ], }); - }); + test('throws when the value of inference accelerator resource does not match any inference accelerators defined in the Task Definition', () => { // GIVEN const stack = new cdk.Stack(); @@ -1222,14 +1202,14 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', InferenceAccelerators: [{ DeviceName: 'device1', DeviceType: 'eia2.medium', }], ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', ResourceRequirements: [{ Type: 'InferenceAccelerator', @@ -1238,7 +1218,7 @@ describe('container definition', () => { Type: 'GPU', Value: '2', }], - }, + }), ], }); }); @@ -1265,9 +1245,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Secrets: [ { Name: 'SECRET', @@ -1299,11 +1279,11 @@ describe('container definition', () => { }, }, ], - }, + }), ], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1349,8 +1329,6 @@ describe('container definition', () => { Version: '2012-10-17', }, }); - - }); test('use a specific secret JSON key as environment variable', () => { @@ -1370,9 +1348,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Secrets: [ { Name: 'SECRET_KEY', @@ -1389,11 +1367,9 @@ describe('container definition', () => { }, }, ], - }, + }), ], }); - - }); test('use a specific secret JSON field as environment variable for a Fargate task', () => { @@ -1413,9 +1389,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Secrets: [ { Name: 'SECRET_KEY', @@ -1432,11 +1408,9 @@ describe('container definition', () => { }, }, ], - }, + }), ], }); - - }); test('can add AWS logging to container definition', () => { @@ -1452,9 +1426,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awslogs', Options: { @@ -1463,11 +1437,11 @@ describe('container definition', () => { 'awslogs-region': { Ref: 'AWS::Region' }, }, }, - }, + }), ], }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1479,8 +1453,6 @@ describe('container definition', () => { Version: '2012-10-17', }, }); - - }); test('can set Health Check with defaults', () => { @@ -1499,20 +1471,18 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ HealthCheck: { Command: ['CMD-SHELL', hcCommand], Interval: 30, Retries: 3, Timeout: 5, }, - }, + }), ], }); - - }); test('throws when setting Health Check with no commands', () => { @@ -1531,7 +1501,7 @@ describe('container definition', () => { // THEN expect(() => { - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { HealthCheck: { @@ -1567,9 +1537,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ HealthCheck: { Command: ['CMD-SHELL', hcCommand], Interval: 20, @@ -1577,11 +1547,9 @@ describe('container definition', () => { Timeout: 5, StartPeriod: 10, }, - }, + }), ], }); - - }); test('can specify Health Check values in array form starting with CMD-SHELL', () => { @@ -1603,9 +1571,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ HealthCheck: { Command: ['CMD-SHELL', hcCommand], Interval: 20, @@ -1613,11 +1581,9 @@ describe('container definition', () => { Timeout: 5, StartPeriod: 10, }, - }, + }), ], }); - - }); test('can specify Health Check values in array form starting with CMD', () => { @@ -1639,9 +1605,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ HealthCheck: { Command: ['CMD', hcCommand], Interval: 20, @@ -1649,11 +1615,9 @@ describe('container definition', () => { Timeout: 5, StartPeriod: 10, }, - }, + }), ], }); - - }); test('can specify private registry credentials', () => { @@ -1673,18 +1637,18 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'user-x/my-app', RepositoryCredentials: { CredentialsParameter: mySecretArn, }, - }, + }), ], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -1698,8 +1662,6 @@ describe('container definition', () => { ], }, }); - - }); describe('_linkContainer works properly', () => { @@ -1756,18 +1718,16 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', LinuxParameters: { Capabilities: {}, }, - }, + }), ], }); - - }); test('before calling addContainer', () => { @@ -1791,9 +1751,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', LinuxParameters: { Capabilities: { @@ -1803,11 +1763,9 @@ describe('container definition', () => { InitProcessEnabled: true, SharedMemorySize: 1024, }, - }, + }), ], }); - - }); test('after calling addContainer', () => { @@ -1833,9 +1791,9 @@ describe('container definition', () => { linuxParameters.dropCapabilities(ecs.Capability.SETUID); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', LinuxParameters: { Capabilities: { @@ -1845,11 +1803,9 @@ describe('container definition', () => { InitProcessEnabled: true, SharedMemorySize: 1024, }, - }, + }), ], }); - - }); test('with one or more host devices', () => { @@ -1874,9 +1830,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', LinuxParameters: { Devices: [ @@ -1887,11 +1843,9 @@ describe('container definition', () => { InitProcessEnabled: true, SharedMemorySize: 1024, }, - }, + }), ], }); - - }); test('with the tmpfs mount for a container', () => { @@ -1917,9 +1871,9 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: 'test', LinuxParameters: { Tmpfs: [ @@ -1931,11 +1885,9 @@ describe('container definition', () => { InitProcessEnabled: true, SharedMemorySize: 1024, }, - }, + }), ], }); - - }); }); @@ -1954,7 +1906,7 @@ describe('container definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Essential: true, @@ -1976,7 +1928,7 @@ describe('container definition', () => { }, ], }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/cross-stack.test.ts b/packages/@aws-cdk/aws-ecs/test/ec2/cross-stack.test.ts index aebf98820d885..4ad3830fa7a9a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/cross-stack.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/cross-stack.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; import { App, Stack } from '@aws-cdk/core'; @@ -50,7 +50,7 @@ describe('cross stack', () => { }); // THEN: it shouldn't throw due to cyclic dependencies - expect(stack2).toHaveResource('AWS::ECS::Service'); + Template.fromStack(stack2).resourceCountIs('AWS::ECS::Service', 1); expectIngress(stack2); @@ -67,7 +67,7 @@ describe('cross stack', () => { }); // THEN: it shouldn't throw due to cyclic dependencies - expect(stack2).toHaveResource('AWS::ECS::Service'); + Template.fromStack(stack2).resourceCountIs('AWS::ECS::Service', 1); expectIngress(stack2); @@ -84,7 +84,7 @@ describe('cross stack', () => { }); // THEN: it shouldn't throw due to cyclic dependencies - expect(stack2).toHaveResource('AWS::ECS::Service'); + Template.fromStack(stack2).resourceCountIs('AWS::ECS::Service', 1); expectIngress(stack2); @@ -92,7 +92,7 @@ describe('cross stack', () => { }); function expectIngress(stack: Stack) { - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { FromPort: 32768, ToPort: 65535, GroupId: { 'Fn::ImportValue': 'Stack1:ExportsOutputFnGetAttDefaultAutoScalingGroupInstanceSecurityGroupFBA881D0GroupId2F7C804A' }, diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-service.test.ts b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-service.test.ts index 7e1f5532fc207..85c5d68568b22 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-service.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-service.test.ts @@ -1,5 +1,4 @@ -import { SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as autoscaling from '@aws-cdk/aws-autoscaling'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elb from '@aws-cdk/aws-elasticloadbalancing'; @@ -36,7 +35,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'Ec2TaskDef0226F28C', }, @@ -77,7 +76,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'Ec2TaskDef0226F28C', }, @@ -94,7 +93,7 @@ describe('ec2 service', () => { EnableExecuteCommand: true, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -168,7 +167,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -231,7 +230,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -351,7 +350,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -442,7 +441,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { @@ -557,7 +556,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -663,7 +662,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { @@ -807,7 +806,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -835,7 +834,7 @@ describe('ec2 service', () => { }, }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::PrivateDnsNamespace', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::PrivateDnsNamespace', { Name: 'scorekeep.com', Vpc: { Ref: 'MyVpcF9F0CA6F', @@ -898,7 +897,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.spreadAcross(ecs.BuiltInAttributes.AVAILABILITY_ZONE)); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'Ec2TaskDef0226F28C', }, @@ -1004,7 +1003,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { CapacityProviderStrategy: [ { CapacityProvider: { @@ -1055,7 +1054,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'Ec2TaskDef0226F28C', }, @@ -1095,7 +1094,7 @@ describe('ec2 service', () => { ServiceName: 'bonjour', }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Bingo', SecurityGroupEgress: [ @@ -1110,7 +1109,7 @@ describe('ec2 service', () => { }, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Rolly', SecurityGroupEgress: [ @@ -1223,7 +1222,7 @@ describe('ec2 service', () => { // THEN expect(service.node.metadataEntry[0].data).toEqual('taskDefinition and launchType are blanked out when using external deployment controller.'); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { Cluster: { Ref: 'EcsCluster97242B84', }, @@ -1329,7 +1328,7 @@ describe('ec2 service', () => { // THEN expect(() => { - SynthUtils.synthesize(stack); + Template.fromStack(stack); }).toThrow(/one essential container/); @@ -1355,15 +1354,13 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Name: 'main', - }, + }), ], }); - - }); test('sets daemon scheduling strategy', () => { @@ -1386,7 +1383,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { SchedulingStrategy: 'DAEMON', DeploymentConfiguration: { MaximumPercent: 100, @@ -1572,7 +1569,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { NetworkConfiguration: { AwsvpcConfiguration: { AssignPublicIp: 'DISABLED', @@ -1647,7 +1644,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementConstraints: [{ Type: 'distinctInstance', }], @@ -1677,7 +1674,7 @@ describe('ec2 service', () => { service.addPlacementConstraints(PlacementConstraint.memberOf('attribute:ecs.instance-type =~ t2.*')); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementConstraints: [{ Expression: 'attribute:ecs.instance-type =~ t2.*', Type: 'memberOf', @@ -1709,7 +1706,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.spreadAcrossInstances()); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Field: 'instanceId', Type: 'spread', @@ -1740,7 +1737,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.spreadAcross(ecs.BuiltInAttributes.AVAILABILITY_ZONE)); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Field: 'attribute:ecs.availability-zone', Type: 'spread', @@ -1841,11 +1838,9 @@ describe('ec2 service', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::ECS::Service', { - PlacementConstraints: undefined, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + PlacementConstraints: Match.absent(), }); - - }); testDeprecated('with both propagateTags and propagateTaskTagsFrom defined', () => { @@ -1892,11 +1887,9 @@ describe('ec2 service', () => { }); // THEN - expect(stack).not.toHaveResource('AWS::ECS::Service', { - PlacementStrategies: undefined, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + PlacementStrategies: Match.absent(), }); - - }); test('with random placement strategy', () => { @@ -1920,7 +1913,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.randomly()); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Type: 'random', }], @@ -1977,7 +1970,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.packedByCpu()); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Field: 'cpu', Type: 'binpack', @@ -2008,7 +2001,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.packedByMemory()); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Field: 'memory', Type: 'binpack', @@ -2039,7 +2032,7 @@ describe('ec2 service', () => { service.addPlacementStrategies(PlacementStrategy.packedBy(ecs.BinPackResource.MEMORY)); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { PlacementStrategies: [{ Field: 'memory', Type: 'binpack', @@ -2272,13 +2265,13 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { Description: 'Load balancer to target', FromPort: 32768, ToPort: 65535, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { Description: 'Load balancer to target', FromPort: 32768, ToPort: 65535, @@ -2320,13 +2313,13 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { Description: 'Load balancer to target', FromPort: 80, ToPort: 80, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { Description: 'Load balancer to target', FromPort: 80, ToPort: 80, @@ -2367,13 +2360,13 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { Description: 'Load balancer to target', FromPort: 8001, ToPort: 8001, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { Description: 'Load balancer to target', FromPort: 8001, ToPort: 8001, @@ -2413,13 +2406,13 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { Description: 'Load balancer to target', FromPort: 8001, ToPort: 8001, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { Description: 'Load balancer to target', FromPort: 8001, ToPort: 8001, @@ -2513,7 +2506,7 @@ describe('ec2 service', () => { lb.addTarget(service); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'web', @@ -2523,7 +2516,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { // if any load balancer is configured and healthCheckGracePeriodSeconds is not // set, then it should default to 60 seconds. HealthCheckGracePeriodSeconds: 60, @@ -2558,7 +2551,7 @@ describe('ec2 service', () => { })); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'web', @@ -2663,7 +2656,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { ContainerName: 'MainContainer', @@ -2678,7 +2671,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -2740,7 +2733,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { ContainerName: 'MainContainer', @@ -2755,7 +2748,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -2851,7 +2844,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { RegistryArn: { @@ -2864,7 +2857,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -2927,7 +2920,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { ContainerName: 'MainContainer', @@ -2942,7 +2935,7 @@ describe('ec2 service', () => { ], }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -3011,7 +3004,7 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { RegistryArn: { 'Fn::GetAtt': ['ServiceCloudmapService046058A4', 'Arn'] }, @@ -3020,8 +3013,6 @@ describe('ec2 service', () => { }, ], }); - - }); test('By default, the container name is the default', () => { @@ -3056,14 +3047,12 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { - ServiceRegistries: [{ + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + ServiceRegistries: [Match.objectLike({ ContainerName: 'main', - ContainerPort: undefined, - }], + ContainerPort: Match.anyValue(), + })], }); - - }); test('For SRV, by default, container name is default container and port is the default container port', () => { @@ -3100,14 +3089,12 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { - ServiceRegistries: [{ + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + ServiceRegistries: [Match.objectLike({ ContainerName: 'main', ContainerPort: 1234, - }], + })], }); - - }); test('allows SRV service discovery to select the container and port', () => { @@ -3147,14 +3134,12 @@ describe('ec2 service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { - ServiceRegistries: [{ + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { + ServiceRegistries: [Match.objectLike({ ContainerName: 'second', ContainerPort: 4321, - }], + })], }); - - }); test('throws if SRV and container is not part of task definition', () => { diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts index 9217e68a412c5..27e10173bbfec 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/ec2-task-definition.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Match, Template } from '@aws-cdk/assertions'; import { Protocol } from '@aws-cdk/aws-ec2'; import { Repository } from '@aws-cdk/aws-ecr'; import * as iam from '@aws-cdk/aws-iam'; @@ -18,14 +18,13 @@ describe('ec2 task definition', () => { new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef'); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EC2'], }); // test error if no container defs? - }); test('with all properties set', () => { @@ -56,7 +55,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ExecutionRoleArn: { 'Fn::GetAtt': [ 'ExecutionRole605A040B', @@ -104,7 +103,7 @@ describe('ec2 task definition', () => { taskDefinition.addPlacementConstraint(ecs.PlacementConstraint.memberOf('attribute:ecs.instance-type =~ t2.*')); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { PlacementConstraints: [ { Expression: 'attribute:ecs.instance-type =~ t2.*', @@ -125,7 +124,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { NetworkMode: ecs.NetworkMode.AWS_VPC, }); @@ -140,7 +139,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { IpcMode: ecs.IpcMode.TASK, }); @@ -155,7 +154,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { PidMode: ecs.PidMode.HOST, }); @@ -194,7 +193,7 @@ describe('ec2 task definition', () => { })); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', ContainerDefinitions: [{ Essential: true, @@ -222,7 +221,7 @@ describe('ec2 task definition', () => { }], }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -288,7 +287,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', ContainerDefinitions: [ { @@ -461,7 +460,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECR::Repository', { + Template.fromStack(stack).hasResourceProperties('AWS::ECR::Repository', { LifecyclePolicy: { // eslint-disable-next-line max-len LifecyclePolicyText: '{"rules":[{"rulePriority":10,"selection":{"tagStatus":"tagged","tagPrefixList":["abc"],"countType":"imageCountMoreThan","countNumber":1},"action":{"type":"expire"}}]}', @@ -470,7 +469,7 @@ describe('ec2 task definition', () => { RepositoryName: 'project-a/amazon-ecs-sample', }); - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', ContainerDefinitions: [{ Essential: true, @@ -543,7 +542,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [{ Essential: true, Memory: 512, @@ -613,7 +612,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [{ Essential: true, Memory: 512, @@ -684,7 +683,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECR::Repository', {}); + Template.fromStack(stack).hasResourceProperties('AWS::ECR::Repository', {}); }); @@ -739,7 +738,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'StackEc2TaskDefF03698CF', ContainerDefinitions: [ { @@ -806,9 +805,9 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', - ContainerDefinitions: [{ + ContainerDefinitions: [Match.objectLike({ MountPoints: [ { ContainerPath: './cache', @@ -816,7 +815,7 @@ describe('ec2 task definition', () => { SourceVolume: 'scratch', }, ], - }], + })], Volumes: [{ Host: { SourcePath: '/tmp/cache', @@ -824,9 +823,8 @@ describe('ec2 task definition', () => { Name: 'scratch', }], }); - - }); + test('correctly sets container dependenices', () => { // GIVEN const stack = new cdk.Stack(); @@ -857,15 +855,15 @@ describe('ec2 task definition', () => { ); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', - ContainerDefinitions: [{ + ContainerDefinitions: [Match.objectLike({ Name: 'dependency1', - }, - { + }), + Match.objectLike({ Name: 'dependency2', - }, - { + }), + Match.objectLike({ Name: 'web', DependsOn: [{ Condition: 'HEALTHY', @@ -875,7 +873,7 @@ describe('ec2 task definition', () => { Condition: 'SUCCESS', ContainerName: 'dependency2', }], - }], + })], }); @@ -906,25 +904,23 @@ describe('ec2 task definition', () => { container.addLink(linkedContainer2); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Links: [ 'linked1:linked', 'linked2', ], Name: 'web', - }, - { + }), + Match.objectLike({ Name: 'linked1', - }, - { + }), + Match.objectLike({ Name: 'linked2', - }, + }), ], }); - - }); test('correctly set policy statement to the task IAM role', () => { @@ -939,7 +935,7 @@ describe('ec2 task definition', () => { })); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -951,9 +947,8 @@ describe('ec2 task definition', () => { ], }, }); - - }); + test('correctly sets volumes from', () => { const stack = new cdk.Stack(); @@ -970,18 +965,16 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { - ContainerDefinitions: [{ + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [Match.objectLike({ VolumesFrom: [ { SourceContainer: 'SourceContainer', ReadOnly: true, }, ], - }], + })], }); - - }); test('correctly set policy statement to the task execution IAM role', () => { @@ -996,7 +989,7 @@ describe('ec2 task definition', () => { })); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -1040,9 +1033,9 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', - ContainerDefinitions: [{ + ContainerDefinitions: [Match.objectLike({ MountPoints: [ { ContainerPath: './cache', @@ -1050,7 +1043,7 @@ describe('ec2 task definition', () => { SourceVolume: 'scratch', }, ], - }], + })], Volumes: [{ Host: { SourcePath: '/tmp/cache', @@ -1058,8 +1051,6 @@ describe('ec2 task definition', () => { Name: 'scratch', }], }); - - }); test('correctly sets placement constraints', () => { @@ -1077,7 +1068,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { PlacementConstraints: [ { Expression: 'attribute:ecs.instance-type =~ t2.*', @@ -1104,7 +1095,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { TaskRoleArn: stack.resolve(taskDefinition.taskRole.roleArn), }); @@ -1117,7 +1108,7 @@ describe('ec2 task definition', () => { const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'Ec2TaskDef'); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { TaskRoleArn: stack.resolve(taskDefinition.taskRole.roleArn), }); @@ -1148,7 +1139,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', Volumes: [{ Name: 'scratch', @@ -1185,7 +1176,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', Volumes: [{ Name: 'scratch', @@ -1219,7 +1210,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', InferenceAccelerators: [{ DeviceName: 'device1', @@ -1252,7 +1243,7 @@ describe('ec2 task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'Ec2TaskDef', InferenceAccelerators: [{ DeviceName: 'device1', diff --git a/packages/@aws-cdk/aws-ecs/test/environment-file.test.ts b/packages/@aws-cdk/aws-ecs/test/environment-file.test.ts index 815973a80e602..abc64332a326b 100644 --- a/packages/@aws-cdk/aws-ecs/test/environment-file.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/environment-file.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; diff --git a/packages/@aws-cdk/aws-ecs/test/external/external-service.test.ts b/packages/@aws-cdk/aws-ecs/test/external/external-service.test.ts index b4a3edf73ea0d..69626f7473fb0 100644 --- a/packages/@aws-cdk/aws-ecs/test/external/external-service.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/external/external-service.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as autoscaling from '@aws-cdk/aws-autoscaling'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as elbv2 from '@aws-cdk/aws-elasticloadbalancingv2'; @@ -29,7 +29,7 @@ describe('external service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'ExternalTaskDef6CCBDB87', }, @@ -79,7 +79,7 @@ describe('external service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'ExternalTaskDef6CCBDB87', }, @@ -165,7 +165,7 @@ describe('external service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'ExternalTaskDef6CCBDB87', }, @@ -177,7 +177,7 @@ describe('external service', () => { ServiceName: 'bonjour', }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Bingo', SecurityGroupEgress: [ @@ -189,7 +189,7 @@ describe('external service', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Rolly', SecurityGroupEgress: [ diff --git a/packages/@aws-cdk/aws-ecs/test/external/external-task-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/external/external-task-definition.test.ts index 3b692f73fe8cf..7963ea0cfa6a1 100644 --- a/packages/@aws-cdk/aws-ecs/test/external/external-task-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/external/external-task-definition.test.ts @@ -1,5 +1,5 @@ -import '@aws-cdk/assert-internal/jest'; import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import { Protocol } from '@aws-cdk/aws-ec2'; import { Repository } from '@aws-cdk/aws-ecr'; import * as iam from '@aws-cdk/aws-iam'; @@ -16,13 +16,11 @@ describe('external task definition', () => { new ecs.ExternalTaskDefinition(stack, 'ExternalTaskDef'); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], }); - - }); test('with all properties set', () => { @@ -43,7 +41,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ExecutionRoleArn: { 'Fn::GetAtt': [ 'ExecutionRole605A040B', @@ -93,7 +91,7 @@ describe('external task definition', () => { })); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], @@ -117,7 +115,7 @@ describe('external task definition', () => { }], }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -180,7 +178,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], @@ -353,7 +351,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECR::Repository', { + Template.fromStack(stack).hasResourceProperties('AWS::ECR::Repository', { LifecyclePolicy: { // eslint-disable-next-line max-len LifecyclePolicyText: '{"rules":[{"rulePriority":10,"selection":{"tagStatus":"tagged","tagPrefixList":["abc"],"countType":"imageCountMoreThan","countNumber":1},"action":{"type":"expire"}}]}', @@ -362,7 +360,7 @@ describe('external task definition', () => { RepositoryName: 'project-a/amazon-ecs-sample', }); - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], @@ -437,7 +435,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], @@ -510,7 +508,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'ExternalTaskDef', NetworkMode: ecs.NetworkMode.BRIDGE, RequiresCompatibilities: ['EXTERNAL'], @@ -585,7 +583,7 @@ describe('external task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECR::Repository', {}); + Template.fromStack(stack).hasResourceProperties('AWS::ECR::Repository', {}); }); diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts index a8dbb29c98b10..3780c43903284 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-service.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { ABSENT, SynthUtils } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as appscaling from '@aws-cdk/aws-applicationautoscaling'; import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import * as ec2 from '@aws-cdk/aws-ec2'; @@ -34,7 +33,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -70,7 +69,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Default/FargateService/SecurityGroup', SecurityGroupEgress: [ { @@ -149,15 +148,15 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE', 'FARGATE_SPOT'], }); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -239,15 +238,15 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Cluster', { - CapacityProviders: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Cluster', { + CapacityProviders: Match.absent(), }); - expect(stack).toHaveResource('AWS::ECS::ClusterCapacityProviderAssociations', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::ClusterCapacityProviderAssociations', { CapacityProviders: ['FARGATE', 'FARGATE_SPOT'], }); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -259,7 +258,7 @@ describe('fargate service', () => { MinimumHealthyPercent: 50, }, // no launch type - LaunchType: ABSENT, + LaunchType: Match.absent(), CapacityProviderStrategy: [ { CapacityProvider: 'FARGATE_SPOT', @@ -326,7 +325,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -354,7 +353,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::ServiceDiscovery::PrivateDnsNamespace', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::PrivateDnsNamespace', { Name: 'scorekeep.com', Vpc: { Ref: 'MyVpcF9F0CA6F', @@ -401,7 +400,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { ContainerName: 'web', @@ -507,7 +506,7 @@ describe('fargate service', () => { // THEN expect(svc.cloudMapService).toBeDefined(); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -634,7 +633,7 @@ describe('fargate service', () => { // THEN expect(service.node.metadataEntry[0].data).toEqual('taskDefinition and launchType are blanked out when using external deployment controller.'); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { Cluster: { Ref: 'EcsCluster97242B84', }, @@ -687,7 +686,7 @@ describe('fargate service', () => { // THEN expect(() => { - SynthUtils.synthesize(stack); + Template.fromStack(stack); }).toThrow(/one essential container/); @@ -711,15 +710,13 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Name: 'main', - }, + }), ], }); - - }); test('allows specifying assignPublicIP as enabled', () => { @@ -740,7 +737,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { NetworkConfiguration: { AwsvpcConfiguration: { AssignPublicIp: 'ENABLED', @@ -769,7 +766,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DeploymentConfiguration: { MinimumHealthyPercent: 0, }, @@ -844,7 +841,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -886,7 +883,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Bingo', SecurityGroupEgress: [ @@ -901,7 +898,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', { GroupDescription: 'Example', GroupName: 'Rolly', SecurityGroupEgress: [ @@ -942,7 +939,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { HealthCheckGracePeriodSeconds: 10, }); @@ -978,7 +975,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { MaxCapacity: 10, MinCapacity: 1, ResourceId: { @@ -1001,7 +998,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { TargetTrackingScalingPolicyConfiguration: { PredefinedMetricSpecification: { PredefinedMetricType: 'ALBRequestCountPerTarget', @@ -1018,7 +1015,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { // if any load balancer is configured and healthCheckGracePeriodSeconds is not // set, then it should default to 60 seconds. HealthCheckGracePeriodSeconds: 60, @@ -1058,7 +1055,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { MaxCapacity: 10, MinCapacity: 1, ResourceId: { @@ -1113,7 +1110,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1125,13 +1122,13 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupIngress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupIngress', { Description: 'Load balancer to target', FromPort: 8000, ToPort: 8000, }); - expect(stack).toHaveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { Description: 'Load balancer to target', FromPort: 8000, ToPort: 8000, @@ -1347,7 +1344,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1359,7 +1356,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 80, Protocol: 'HTTP', }); @@ -1399,7 +1396,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1411,7 +1408,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 80, Protocol: 'HTTP', }); @@ -1451,7 +1448,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1463,7 +1460,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 443, Protocol: 'HTTPS', }); @@ -1504,7 +1501,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1516,7 +1513,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 83, Protocol: 'HTTP', }); @@ -1556,7 +1553,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1568,7 +1565,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 80, Protocol: 'TCP', }); @@ -1608,7 +1605,7 @@ describe('fargate service', () => { ); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { LoadBalancers: [ { ContainerName: 'MainContainer', @@ -1620,7 +1617,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::TargetGroup', { + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::TargetGroup', { Port: 81, Protocol: 'TCP', }); @@ -1655,7 +1652,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalableTarget', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalableTarget', { ScheduledActions: [ { ScalableTargetAction: { @@ -1698,7 +1695,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'StepScaling', ScalingTargetId: { Ref: 'ServiceTaskCountTarget23E25614', @@ -1741,7 +1738,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { PredefinedMetricSpecification: { PredefinedMetricType: 'ECSServiceAverageCPUUtilization' }, @@ -1775,7 +1772,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { PredefinedMetricSpecification: { PredefinedMetricType: 'ECSServiceAverageMemoryUtilization' }, @@ -1810,7 +1807,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ApplicationAutoScaling::ScalingPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::ApplicationAutoScaling::ScalingPolicy', { PolicyType: 'TargetTrackingScaling', TargetTrackingScalingPolicyConfiguration: { CustomizedMetricSpecification: { @@ -1878,7 +1875,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -1939,7 +1936,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -2001,7 +1998,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ServiceDiscovery::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ServiceDiscovery::Service', { DnsConfig: { DnsRecords: [ { @@ -2065,7 +2062,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResourceLike('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { ServiceRegistries: [ { RegistryArn: { 'Fn::GetAtt': ['ServiceCloudmapService046058A4', 'Arn'] }, @@ -2168,7 +2165,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { DeploymentConfiguration: { MaximumPercent: 200, MinimumHealthyPercent: 50, @@ -2233,7 +2230,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::Service', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', { TaskDefinition: { Ref: 'FargateTaskDefC6FB60B4', }, @@ -2270,7 +2267,7 @@ describe('fargate service', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -2344,7 +2341,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -2407,7 +2404,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -2527,7 +2524,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -2618,7 +2615,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { @@ -2733,7 +2730,7 @@ describe('fargate service', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -2839,7 +2836,7 @@ describe('fargate service', () => { ], }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { Statement: [ { diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-task-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-task-definition.test.ts index 1f42e09cf83ac..e0b7afca3389f 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/fargate-task-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/fargate-task-definition.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../../lib'; @@ -11,7 +11,7 @@ describe('fargate task definition', () => { new ecs.FargateTaskDefinition(stack, 'FargateTaskDef'); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Family: 'FargateTaskDef', NetworkMode: ecs.NetworkMode.AWS_VPC, RequiresCompatibilities: ['FARGATE'], @@ -32,7 +32,7 @@ describe('fargate task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Cpu: '128', Memory: '1024', }); @@ -72,7 +72,7 @@ describe('fargate task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Cpu: '128', ExecutionRoleArn: { 'Fn::GetAtt': [ @@ -265,7 +265,7 @@ describe('fargate task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Cpu: '1024', Family: 'FargateTaskDef', Memory: '2048', @@ -299,7 +299,7 @@ describe('fargate task definition', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { Cpu: '1024', Family: 'FargateTaskDef', Memory: '2048', diff --git a/packages/@aws-cdk/aws-ecs/test/firelens-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/firelens-log-driver.test.ts index 6ab96b05df364..547382ab8d3de 100644 --- a/packages/@aws-cdk/aws-ecs/test/firelens-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/firelens-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as ssm from '@aws-cdk/aws-ssm'; import * as cdk from '@aws-cdk/core'; @@ -24,23 +24,21 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awsfirelens', }, - }, - { + }), + Match.objectLike({ Essential: true, FirelensConfiguration: { Type: 'fluentbit', }, - }, + }), ], }); - - }); test('create a firelens log driver with secret options', () => { @@ -71,9 +69,9 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awsfirelens', Options: { @@ -116,19 +114,19 @@ describe('firelens log driver', () => { }, ], }, - }, - { + }), + Match.objectLike({ Essential: true, FirelensConfiguration: { Type: 'fluentbit', }, - }, + }), ], }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ + Statement: Match.arrayWith([ { Action: [ 'secretsmanager:GetSecretValue', @@ -168,12 +166,10 @@ describe('firelens log driver', () => { ], }, }, - ], + ]), Version: '2012-10-17', }, }); - - }); test('create a firelens log driver to route logs to CloudWatch Logs with Fluent Bit', () => { @@ -193,9 +189,9 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awsfirelens', Options: { @@ -206,17 +202,15 @@ describe('firelens log driver', () => { log_stream_prefix: 'from-fluent-bit', }, }, - }, - { + }), + Match.objectLike({ Essential: true, FirelensConfiguration: { Type: 'fluentbit', }, - }, + }), ], }); - - }); test('create a firelens log driver to route logs to kinesis firehose Logs with Fluent Bit', () => { @@ -234,9 +228,9 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'awsfirelens', Options: { @@ -245,17 +239,15 @@ describe('firelens log driver', () => { delivery_stream: 'my-stream', }, }, - }, - { + }), + Match.objectLike({ Essential: true, FirelensConfiguration: { Type: 'fluentbit', }, - }, + }), ], }); - - }); describe('Firelens Configuration', () => { @@ -270,7 +262,7 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ { Essential: true, @@ -283,7 +275,6 @@ describe('firelens log driver', () => { }, ], }); - }); test('fluent-bit log router container with options', () => { @@ -304,9 +295,9 @@ describe('firelens log driver', () => { }); // THEN - expect(stack2).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack2).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Essential: true, MemoryReservation: 50, Name: 'log_router', @@ -318,11 +309,9 @@ describe('firelens log driver', () => { 'config-file-value': 'arn:aws:s3:::mybucket/fluent.conf', }, }, - }, + }), ], }); - - }); test('fluent-bit log router with file config type', () => { @@ -342,9 +331,9 @@ describe('firelens log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Essential: true, MemoryReservation: 50, Name: 'log_router', @@ -356,11 +345,9 @@ describe('firelens log driver', () => { 'config-file-value': '/my/working/dir/firelens/config', }, }, - }, + }), ], }); - - }); }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/fluentd-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/fluentd-log-driver.test.ts index 81c17b8c0b76f..7bd81fed41221 100644 --- a/packages/@aws-cdk/aws-ecs/test/fluentd-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/fluentd-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -10,8 +10,6 @@ describe('fluentd log driver', () => { beforeEach(() => { stack = new cdk.Stack(); td = new ecs.Ec2TaskDefinition(stack, 'TaskDefinition'); - - }); test('create a fluentd log driver with options', () => { @@ -25,20 +23,18 @@ describe('fluentd log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'fluentd', Options: { tag: 'hello', }, }, - }, + }), ], }); - - }); test('create a fluentd log driver without options', () => { @@ -50,17 +46,15 @@ describe('fluentd log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'fluentd', }, - }, + }), ], }); - - }); test('create a fluentd log driver with all possible options', () => { @@ -91,9 +85,9 @@ describe('fluentd log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'fluentd', Options: { @@ -109,11 +103,9 @@ describe('fluentd log driver', () => { 'env-regex': '[0-9]{1}', }, }, - }, + }), ], }); - - }); test('create a fluentd log driver using fluentd', () => { @@ -125,16 +117,14 @@ describe('fluentd log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'fluentd', }, - }, + }), ], }); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/gelf-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/gelf-log-driver.test.ts index e8cdce10736e1..f6800bb48ac01 100644 --- a/packages/@aws-cdk/aws-ecs/test/gelf-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/gelf-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -25,20 +25,18 @@ describe('gelf log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'gelf', Options: { 'gelf-address': 'my-gelf-address', }, }, - }, + }), ], }); - - }); test('create a gelf log driver using gelf with minimum options', () => { @@ -52,19 +50,17 @@ describe('gelf log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'gelf', Options: { 'gelf-address': 'my-gelf-address', }, }, - }, + }), ], }); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/images/tag-parameter-container-image.test.ts b/packages/@aws-cdk/aws-ecs/test/images/tag-parameter-container-image.test.ts index 3f409739d76ed..9ff3023b1e965 100644 --- a/packages/@aws-cdk/aws-ecs/test/images/tag-parameter-container-image.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/images/tag-parameter-container-image.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { SynthUtils } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as ecr from '@aws-cdk/aws-ecr'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../../lib'; @@ -16,10 +15,8 @@ describe('tag parameter container image', () => { }); expect(() => { - SynthUtils.synthesize(stack); + Template.fromStack(stack); }).toThrow(/TagParameterContainerImage must be used in a container definition when using tagParameterName/); - - }); test('throws an error when tagParameterValue() is used without binding the image', () => { @@ -32,10 +29,8 @@ describe('tag parameter container image', () => { }); expect(() => { - SynthUtils.synthesize(stack); + Template.fromStack(stack); }).toThrow(/TagParameterContainerImage must be used in a container definition when using tagParameterValue/); - - }); test('can be used in a cross-account manner', () => { @@ -67,7 +62,7 @@ describe('tag parameter container image', () => { }); // THEN - expect(pipelineStack).toHaveResourceLike('AWS::ECR::Repository', { + Template.fromStack(pipelineStack).hasResourceProperties('AWS::ECR::Repository', { RepositoryName: repositoryName, RepositoryPolicyText: { Statement: [{ @@ -89,12 +84,12 @@ describe('tag parameter container image', () => { }], }, }); - expect(serviceStack).toHaveResourceLike('AWS::IAM::Role', { + Template.fromStack(serviceStack).hasResourceProperties('AWS::IAM::Role', { RoleName: 'servicestackionexecutionrolee7e2d9a783a54eb795f4', }); - expect(serviceStack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(serviceStack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ Image: { 'Fn::Join': ['', [ { @@ -126,11 +121,9 @@ describe('tag parameter container image', () => { { Ref: 'ServiceTaskDefinitionContainerImageTagParamCEC9D0BA' }, ]], }, - }, + }), ], }); - - }); }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/journald-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/journald-log-driver.test.ts index fdf67efc3bb4f..b3f25650b9e58 100644 --- a/packages/@aws-cdk/aws-ecs/test/journald-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/journald-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -10,8 +10,6 @@ describe('journald log driver', () => { beforeEach(() => { stack = new cdk.Stack(); td = new ecs.Ec2TaskDefinition(stack, 'TaskDefinition'); - - }); test('create a journald log driver with options', () => { @@ -25,20 +23,18 @@ describe('journald log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'journald', Options: { tag: 'hello', }, }, - }, + }), ], }); - - }); test('create a journald log driver without options', () => { @@ -50,17 +46,15 @@ describe('journald log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'journald', }, - }, + }), ], }); - - }); test('create a journald log driver using journald', () => { @@ -72,17 +66,15 @@ describe('journald log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'journald', Options: {}, }, - }, + }), ], }); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/json-file-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/json-file-log-driver.test.ts index 0c21ff2d0b5f1..ed2622dc79eaa 100644 --- a/packages/@aws-cdk/aws-ecs/test/json-file-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/json-file-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -25,20 +25,18 @@ describe('json file log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'json-file', Options: { env: 'hello', }, }, - }, + }), ], }); - - }); test('create a json-file log driver without options', () => { @@ -50,17 +48,15 @@ describe('json file log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'json-file', }, - }, + }), ], }); - - }); test('create a json-file log driver using json-file', () => { @@ -72,17 +68,15 @@ describe('json file log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'json-file', Options: {}, }, - }, + }), ], }); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/splunk-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/splunk-log-driver.test.ts index cb7678d9bc6e4..b33b4155615a4 100644 --- a/packages/@aws-cdk/aws-ecs/test/splunk-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/splunk-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as secretsmanager from '@aws-cdk/aws-secretsmanager'; import * as ssm from '@aws-cdk/aws-ssm'; import * as cdk from '@aws-cdk/core'; @@ -28,9 +28,9 @@ describe('splunk log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'splunk', Options: { @@ -45,11 +45,9 @@ describe('splunk log driver', () => { }, }], }, - }, + }), ], }); - - }); test('create a splunk log driver using splunk with minimum options', () => { @@ -64,9 +62,9 @@ describe('splunk log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'splunk', Options: { @@ -81,11 +79,9 @@ describe('splunk log driver', () => { }, }], }, - }, + }), ], }); - - }); test('create a splunk log driver using splunk with sourcetype defined', () => { @@ -101,9 +97,9 @@ describe('splunk log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'splunk', Options: { @@ -119,11 +115,9 @@ describe('splunk log driver', () => { }, }], }, - }, + }), ], }); - - }); test('create a splunk log driver using secret splunk token from a new secret', () => { @@ -139,9 +133,9 @@ describe('splunk log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'splunk', Options: { @@ -156,11 +150,9 @@ describe('splunk log driver', () => { }, ], }, - }, + }), ], }); - - }); test('create a splunk log driver using secret splunk token from systems manager parameter store', () => { @@ -179,9 +171,9 @@ describe('splunk log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'splunk', Options: { @@ -213,11 +205,9 @@ describe('splunk log driver', () => { }, ], }, - }, + }), ], }); - - }); test('throws when neither token nor secret token are provided', () => { @@ -230,7 +220,5 @@ describe('splunk log driver', () => { memoryLimitMiB: 128, }); }).toThrow('Please provide either token or secretToken.'); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/syslog-log-driver.test.ts b/packages/@aws-cdk/aws-ecs/test/syslog-log-driver.test.ts index ae32f55ecd863..fa77acb52e09b 100644 --- a/packages/@aws-cdk/aws-ecs/test/syslog-log-driver.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/syslog-log-driver.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -10,8 +10,6 @@ describe('syslog log driver', () => { beforeEach(() => { stack = new cdk.Stack(); td = new ecs.Ec2TaskDefinition(stack, 'TaskDefinition'); - - }); test('create a syslog log driver with options', () => { @@ -25,20 +23,18 @@ describe('syslog log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'syslog', Options: { tag: 'hello', }, }, - }, + }), ], }); - - }); test('create a syslog log driver without options', () => { @@ -50,17 +46,15 @@ describe('syslog log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'syslog', }, - }, + }), ], }); - - }); test('create a syslog log driver using syslog', () => { @@ -72,17 +66,15 @@ describe('syslog log driver', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ - { + Match.objectLike({ LogConfiguration: { LogDriver: 'syslog', Options: {}, }, - }, + }), ], }); - - }); }); diff --git a/packages/@aws-cdk/aws-ecs/test/task-definition.test.ts b/packages/@aws-cdk/aws-ecs/test/task-definition.test.ts index 07b3a8211da06..11e383565af81 100644 --- a/packages/@aws-cdk/aws-ecs/test/task-definition.test.ts +++ b/packages/@aws-cdk/aws-ecs/test/task-definition.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import * as ecs from '../lib'; @@ -17,7 +17,7 @@ describe('task definition', () => { }); // THEN - expect(stack).toHaveResource('AWS::ECS::TaskDefinition', { + Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', { NetworkMode: 'awsvpc', }); diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index 1395546b46f73..e5554ffcf8ba2 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -89,8 +89,8 @@ "@types/sinon": "^9.0.11", "@types/yaml": "1.9.6", "aws-sdk": "^2.848.0", - "cdk8s": "^1.3.26", - "cdk8s-plus-21": "^1.0.0-beta.72", + "cdk8s": "^1.3.32", + "cdk8s-plus-21": "^1.0.0-beta.73", "jest": "^27.4.7", "sinon": "^9.2.4" }, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts index 85ae9d143f0e2..345583bf9e5f8 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts @@ -192,8 +192,11 @@ export abstract class BaseLoadBalancer extends Resource { /** * The VPC this load balancer has been created in. + * + * This property is always defined (not `null` or `undefined`) for sub-classes of `BaseLoadBalancer`. */ - public readonly vpc: ec2.IVpc; + public readonly vpc?: ec2.IVpc; + /** * Attributes set on this load balancer */ diff --git a/packages/@aws-cdk/aws-forecast/.eslintrc.js b/packages/@aws-cdk/aws-forecast/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-forecast/.gitignore b/packages/@aws-cdk/aws-forecast/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-forecast/.npmignore b/packages/@aws-cdk/aws-forecast/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-forecast/LICENSE b/packages/@aws-cdk/aws-forecast/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-forecast/NOTICE b/packages/@aws-cdk/aws-forecast/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-forecast/README.md b/packages/@aws-cdk/aws-forecast/README.md new file mode 100644 index 0000000000000..5d81bb62ad1ec --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/README.md @@ -0,0 +1,31 @@ +# AWS::Forecast Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as forecast from '@aws-cdk/aws-forecast'; +``` + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::Forecast](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Forecast.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) + + diff --git a/packages/@aws-cdk/aws-forecast/jest.config.js b/packages/@aws-cdk/aws-forecast/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-forecast/lib/index.ts b/packages/@aws-cdk/aws-forecast/lib/index.ts new file mode 100644 index 0000000000000..9a67512fd1db3 --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::Forecast CloudFormation Resources: +export * from './forecast.generated'; diff --git a/packages/@aws-cdk/aws-forecast/package.json b/packages/@aws-cdk/aws-forecast/package.json new file mode 100644 index 0000000000000..e4431039dc27c --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-cdk/aws-forecast", + "version": "0.0.0", + "description": "AWS::Forecast Construct Library", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.Forecast", + "packageId": "Amazon.CDK.AWS.Forecast", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.forecast", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "forecast" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-forecast", + "module": "aws_cdk.aws_forecast" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-forecast" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::Forecast", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::Forecast", + "aws-forecast" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-forecast/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-forecast/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-forecast/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-codeguruprofiler/test/codeguruprofiler.test.ts b/packages/@aws-cdk/aws-forecast/test/forecast.test.ts similarity index 73% rename from packages/@aws-cdk/aws-codeguruprofiler/test/codeguruprofiler.test.ts rename to packages/@aws-cdk/aws-forecast/test/forecast.test.ts index c4505ad966984..465c7bdea0693 100644 --- a/packages/@aws-cdk/aws-codeguruprofiler/test/codeguruprofiler.test.ts +++ b/packages/@aws-cdk/aws-forecast/test/forecast.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import '@aws-cdk/assertions'; import {} from '../lib'; test('No tests are specified for this package', () => { diff --git a/packages/@aws-cdk/aws-fsx/package.json b/packages/@aws-cdk/aws-fsx/package.json index fb7cd9f8ef29d..0b0c1f0426004 100644 --- a/packages/@aws-cdk/aws-fsx/package.json +++ b/packages/@aws-cdk/aws-fsx/package.json @@ -81,7 +81,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-fsx/test/lustre-file-system.test.ts b/packages/@aws-cdk/aws-fsx/test/lustre-file-system.test.ts index ad4c4462d8c58..6f581475dbe3d 100644 --- a/packages/@aws-cdk/aws-fsx/test/lustre-file-system.test.ts +++ b/packages/@aws-cdk/aws-fsx/test/lustre-file-system.test.ts @@ -1,5 +1,5 @@ import { strictEqual } from 'assert'; -import { expect as expectCDK, haveResource, ResourcePart } from '@aws-cdk/assert-internal'; +import { Template } from '@aws-cdk/assertions'; import { ISubnet, Port, SecurityGroup, Subnet, Vpc } from '@aws-cdk/aws-ec2'; import { Key } from '@aws-cdk/aws-kms'; import { Aws, Stack, Token } from '@aws-cdk/core'; @@ -35,15 +35,15 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem')); - expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroup')); + Template.fromStack(stack).hasResource('AWS::FSx::FileSystem', {}); + Template.fromStack(stack).hasResource('AWS::EC2::SecurityGroup', {}); strictEqual( fileSystem.dnsName, `${fileSystem.fileSystemId}.fsx.${stack.region}.${Aws.URL_SUFFIX}`); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResource('AWS::FSx::FileSystem', { DeletionPolicy: 'Retain', - }, ResourcePart.CompleteDefinition)); + }); }); test('file system is created correctly when security group is provided', () => { @@ -63,8 +63,8 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem')); - expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroup')); + Template.fromStack(stack).hasResource('AWS::FSx::FileSystem', {}); + Template.fromStack(stack).hasResource('AWS::EC2::SecurityGroup', {}); }); test('encrypted file system is created correctly with custom KMS', () => { @@ -88,11 +88,11 @@ describe('FSx for Lustre File System', () => { * in generated CDK, hence hardcoding the MD5 hash here for assertion. Assumption is that the path of the Key wont * change in this UT. Checked the unique id by generating the cloud formation stack. */ - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { KmsKeyId: { Ref: 'customKeyFSDDB87C6D', }, - })); + }); }); test('file system is created correctly when weekly maintenance time is provided', () => { @@ -118,13 +118,13 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: 'SCRATCH_2', WeeklyMaintenanceStartTime: '7:12:34', }, - })); - expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroup')); + }); + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', {}); }); describe('when validating props', () => { @@ -145,13 +145,13 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_2, ExportPath: exportPath, ImportPath: importPath, }, - })); + }); }); test('export and import paths are Tokens', () => { @@ -172,13 +172,13 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_2, ExportPath: exportPathResolved, ImportPath: importPathResolved, }, - })); + }); }); test('only export path is Token', () => { @@ -299,12 +299,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_2, ImportedFileChunkSize: size, }, - })); + }); }); test.each([ @@ -342,12 +342,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_2, ImportPath: importPath, }, - })); + }); }); test('import path is Token', () => { @@ -364,12 +364,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_2, ImportPath: importPathResolved, }, - })); + }); }); test('invalid import path format', () => { @@ -428,12 +428,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.PERSISTENT_1, PerUnitStorageThroughput: throughput, }, - })); + }); }); test('invalid perUnitStorageThroughput', () => { @@ -489,12 +489,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: deploymentType, }, StorageCapacity: value, - })); + }); }); test.each([ @@ -529,12 +529,12 @@ describe('FSx for Lustre File System', () => { vpcSubnet, }); - expectCDK(stack).to(haveResource('AWS::FSx::FileSystem', { + Template.fromStack(stack).hasResourceProperties('AWS::FSx::FileSystem', { LustreConfiguration: { DeploymentType: LustreDeploymentType.SCRATCH_1, }, StorageCapacity: validValue, - })); + }); }); test.each([1, 3601])('invalid value of %d for storage capacity with SCRATCH_1', (invalidValue: number) => { @@ -566,8 +566,8 @@ describe('FSx for Lustre File System', () => { fs.connections.allowToAnyIpv4(Port.tcp(443)); - expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroupEgress', { + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { GroupId: 'sg-123456789', - })); + }); }); }); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-inspectorv2/.eslintrc.js b/packages/@aws-cdk/aws-inspectorv2/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-inspectorv2/.gitignore b/packages/@aws-cdk/aws-inspectorv2/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-inspectorv2/.npmignore b/packages/@aws-cdk/aws-inspectorv2/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-inspectorv2/LICENSE b/packages/@aws-cdk/aws-inspectorv2/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-inspectorv2/NOTICE b/packages/@aws-cdk/aws-inspectorv2/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-inspectorv2/README.md b/packages/@aws-cdk/aws-inspectorv2/README.md new file mode 100644 index 0000000000000..5d16d199514e3 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/README.md @@ -0,0 +1,31 @@ +# AWS::InspectorV2 Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as inspector from '@aws-cdk/aws-inspectorv2'; +``` + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::InspectorV2](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_InspectorV2.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) + + diff --git a/packages/@aws-cdk/aws-inspectorv2/jest.config.js b/packages/@aws-cdk/aws-inspectorv2/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-inspectorv2/lib/index.ts b/packages/@aws-cdk/aws-inspectorv2/lib/index.ts new file mode 100644 index 0000000000000..d41ac2a9185de --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::InspectorV2 CloudFormation Resources: +export * from './inspectorv2.generated'; diff --git a/packages/@aws-cdk/aws-inspectorv2/package.json b/packages/@aws-cdk/aws-inspectorv2/package.json new file mode 100644 index 0000000000000..58bc8bd45bf6b --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-cdk/aws-inspectorv2", + "version": "0.0.0", + "description": "AWS::InspectorV2 Construct Library", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.InspectorV2", + "packageId": "Amazon.CDK.AWS.InspectorV2", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.inspectorv2", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "inspectorv2" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-inspectorv2", + "module": "aws_cdk.aws_inspectorv2" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-inspectorv2" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::InspectorV2", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::InspectorV2", + "aws-inspectorv2" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-inspectorv2/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-inspectorv2/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-inspectorv2/test/inspectorv2.test.ts b/packages/@aws-cdk/aws-inspectorv2/test/inspectorv2.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-inspectorv2/test/inspectorv2.test.ts @@ -0,0 +1,6 @@ +import '@aws-cdk/assertions'; +import {} from '../lib'; + +test('No tests are specified for this package', () => { + expect(true).toBe(true); +}); diff --git a/packages/@aws-cdk/aws-kinesis/package.json b/packages/@aws-cdk/aws-kinesis/package.json index 37495af6cf1cd..0b1aea08d72df 100644 --- a/packages/@aws-cdk/aws-kinesis/package.json +++ b/packages/@aws-cdk/aws-kinesis/package.json @@ -79,7 +79,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-kinesis/test/stream.test.ts b/packages/@aws-cdk/aws-kinesis/test/stream.test.ts index 8e4fa385133dd..e1fce397cce4c 100644 --- a/packages/@aws-cdk/aws-kinesis/test/stream.test.ts +++ b/packages/@aws-cdk/aws-kinesis/test/stream.test.ts @@ -1,5 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; -import { arrayWith } from '@aws-cdk/assert-internal'; +import { Match, Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; import { testFutureBehavior, testLegacyBehavior } from '@aws-cdk/cdk-build-tools'; @@ -16,7 +15,7 @@ describe('Kinesis data streams', () => { new Stream(stack, 'MyStream'); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -72,7 +71,7 @@ describe('Kinesis data streams', () => { new Stream(stack, 'MyStream'); new Stream(stack, 'MyOtherStream'); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -161,7 +160,7 @@ describe('Kinesis data streams', () => { shardCount: 2, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -218,7 +217,7 @@ describe('Kinesis data streams', () => { retentionPeriod: Duration.hours(168), }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -292,7 +291,7 @@ describe('Kinesis data streams', () => { }); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -335,7 +334,7 @@ describe('Kinesis data streams', () => { }); // THEN - expect(stack).toHaveResource('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { ShardCount: 1, StreamModeDetails: { StreamMode: StreamMode.PROVISIONED, @@ -357,11 +356,11 @@ describe('Kinesis data streams', () => { encryption: StreamEncryption.KMS, }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'Created by Default/MyStream', }); - expect(stack).toHaveResource('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { StreamEncryption: { EncryptionType: 'KMS', KeyId: stack.resolve(stream.encryptionKey?.keyArn), @@ -381,11 +380,11 @@ describe('Kinesis data streams', () => { encryptionKey: explicitKey, }); - expect(stack).toHaveResource('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { Description: 'Explicit Key', }); - expect(stack).toHaveResource('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { ShardCount: 1, StreamModeDetails: { StreamMode: StreamMode.PROVISIONED, @@ -405,7 +404,7 @@ describe('Kinesis data streams', () => { streamMode: StreamMode.PROVISIONED, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -462,7 +461,7 @@ describe('Kinesis data streams', () => { streamMode: StreamMode.ON_DEMAND, }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -531,17 +530,17 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantRead(user); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: 'kms:Decrypt', Effect: 'Allow', Resource: stack.resolve(stream.encryptionKey?.keyArn), - }), + }]), }, }); - expect(stack).toHaveResourceLike('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { StreamEncryption: { KeyId: stack.resolve(stream.encryptionKey?.keyArn), }, @@ -559,7 +558,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantRead(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStreamKey76F3300E: { Type: 'AWS::KMS::Key', @@ -693,17 +692,17 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantWrite(user); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: ['kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*'], Effect: 'Allow', Resource: stack.resolve(stream.encryptionKey?.keyArn), - }), + }]), }, }); - expect(stack).toHaveResourceLike('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { StreamEncryption: { KeyId: stack.resolve(stream.encryptionKey?.keyArn), }, @@ -721,7 +720,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantWrite(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStreamKey76F3300E: { Type: 'AWS::KMS::Key', @@ -847,17 +846,17 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantReadWrite(user); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: ['kms:Decrypt', 'kms:Encrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*'], Effect: 'Allow', Resource: stack.resolve(stream.encryptionKey?.keyArn), - }), + }]), }, }); - expect(stack).toHaveResourceLike('AWS::Kinesis::Stream', { + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::Stream', { StreamEncryption: { KeyId: stack.resolve(stream.encryptionKey?.keyArn), }, @@ -875,7 +874,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantReadWrite(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStreamKey76F3300E: { Type: 'AWS::KMS::Key', @@ -1009,7 +1008,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantRead(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -1100,7 +1099,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantWrite(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -1183,7 +1182,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grantReadWrite(user); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -1276,7 +1275,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stack, 'MyUser'); stream.grant(user, 'kinesis:DescribeStream'); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -1361,7 +1360,7 @@ describe('Kinesis data streams', () => { const user = new iam.User(stackB, 'UserWhoNeedsAccess'); streamFromStackA.grantRead(user); - expect(stackA).toMatchTemplate({ + Template.fromStack(stackA).templateMatches({ Resources: { MyStream5C050E93: { Type: 'AWS::Kinesis::Stream', @@ -1446,15 +1445,15 @@ describe('Kinesis data streams', () => { const user = new iam.User(stackB, 'UserWhoNeedsAccess'); streamFromStackA.grantRead(user); - expect(stackB).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stackB).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: 'kms:Decrypt', Effect: 'Allow', Resource: { 'Fn::ImportValue': 'stackA:ExportsOutputFnGetAttMyStreamKey76F3300EArn190947B4', }, - }), + }]), }, }); }); @@ -1473,7 +1472,7 @@ describe('Kinesis data streams', () => { retentionPeriod: Duration.hours(parameter.valueAsNumber), }); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Parameters: { myretentionperiod: { Type: 'Number', diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/.eslintrc.js b/packages/@aws-cdk/aws-kinesisanalyticsv2/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/.gitignore b/packages/@aws-cdk/aws-kinesisanalyticsv2/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/.npmignore b/packages/@aws-cdk/aws-kinesisanalyticsv2/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/LICENSE b/packages/@aws-cdk/aws-kinesisanalyticsv2/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/NOTICE b/packages/@aws-cdk/aws-kinesisanalyticsv2/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/README.md b/packages/@aws-cdk/aws-kinesisanalyticsv2/README.md new file mode 100644 index 0000000000000..86915437e77c6 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/README.md @@ -0,0 +1,31 @@ +# AWS::KinesisAnalyticsV2 Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as kinesisanalytics from '@aws-cdk/aws-kinesisanalyticsv2'; +``` + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::KinesisAnalyticsV2](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_KinesisAnalyticsV2.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) + + diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/jest.config.js b/packages/@aws-cdk/aws-kinesisanalyticsv2/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/lib/index.ts b/packages/@aws-cdk/aws-kinesisanalyticsv2/lib/index.ts new file mode 100644 index 0000000000000..d164240b822cf --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::KinesisAnalyticsV2 CloudFormation Resources: +export * from './kinesisanalyticsv2.generated'; diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json b/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json new file mode 100644 index 0000000000000..6efbd4c780c43 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-cdk/aws-kinesisanalyticsv2", + "version": "0.0.0", + "description": "AWS::KinesisAnalyticsV2 Construct Library", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.KinesisAnalyticsV2", + "packageId": "Amazon.CDK.AWS.KinesisAnalyticsV2", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.kinesisanalyticsv2", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "kinesisanalyticsv2" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-kinesisanalyticsv2", + "module": "aws_cdk.aws_kinesisanalyticsv2" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-kinesisanalyticsv2" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::KinesisAnalyticsV2", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::KinesisAnalyticsV2", + "aws-kinesisanalyticsv2" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-kinesisanalyticsv2/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-kinesisanalyticsv2/test/kinesisanalyticsv2.test.ts b/packages/@aws-cdk/aws-kinesisanalyticsv2/test/kinesisanalyticsv2.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisanalyticsv2/test/kinesisanalyticsv2.test.ts @@ -0,0 +1,6 @@ +import '@aws-cdk/assertions'; +import {} from '../lib'; + +test('No tests are specified for this package', () => { + expect(true).toBe(true); +}); diff --git a/packages/@aws-cdk/aws-kinesisvideo/.eslintrc.js b/packages/@aws-cdk/aws-kinesisvideo/.eslintrc.js new file mode 100644 index 0000000000000..2658ee8727166 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/.eslintrc.js @@ -0,0 +1,3 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/eslintrc'); +baseConfig.parserOptions.project = __dirname + '/tsconfig.json'; +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-kinesisvideo/.gitignore b/packages/@aws-cdk/aws-kinesisvideo/.gitignore new file mode 100644 index 0000000000000..62ebc95d75ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/.gitignore @@ -0,0 +1,19 @@ +*.js +*.js.map +*.d.ts +tsconfig.json +node_modules +*.generated.ts +dist +.jsii + +.LAST_BUILD +.nyc_output +coverage +.nycrc +.LAST_PACKAGE +*.snk +nyc.config.js +!.eslintrc.js +!jest.config.js +junit.xml diff --git a/packages/@aws-cdk/aws-kinesisvideo/.npmignore b/packages/@aws-cdk/aws-kinesisvideo/.npmignore new file mode 100644 index 0000000000000..f931fede67c44 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/.npmignore @@ -0,0 +1,29 @@ +# Don't include original .ts files when doing `npm pack` +*.ts +!*.d.ts +coverage +.nyc_output +*.tgz + +dist +.LAST_PACKAGE +.LAST_BUILD +!*.js + +# Include .jsii +!.jsii + +*.snk + +*.tsbuildinfo + +tsconfig.json + +.eslintrc.js +jest.config.js + +# exclude cdk artifacts +**/cdk.out +junit.xml +test/ +!*.lit.ts diff --git a/packages/@aws-cdk/aws-kinesisvideo/LICENSE b/packages/@aws-cdk/aws-kinesisvideo/LICENSE new file mode 100644 index 0000000000000..82ad00bb02d0b --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/@aws-cdk/aws-kinesisvideo/NOTICE b/packages/@aws-cdk/aws-kinesisvideo/NOTICE new file mode 100644 index 0000000000000..1b7adbb891265 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/NOTICE @@ -0,0 +1,2 @@ +AWS Cloud Development Kit (AWS CDK) +Copyright 2018-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-kinesisvideo/README.md b/packages/@aws-cdk/aws-kinesisvideo/README.md new file mode 100644 index 0000000000000..2d0d2df9733fb --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/README.md @@ -0,0 +1,31 @@ +# AWS::KinesisVideo Construct Library + + +--- + +![cfn-resources: Stable](https://img.shields.io/badge/cfn--resources-stable-success.svg?style=for-the-badge) + +> All classes with the `Cfn` prefix in this module ([CFN Resources]) are always stable and safe to use. +> +> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib + +--- + + + +This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. + +```ts nofixture +import * as kinesisvideo from '@aws-cdk/aws-kinesisvideo'; +``` + + + +There are no hand-written ([L2](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib)) constructs for this service yet. +However, you can still use the automatically generated [L1](https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_l1_using) constructs, and use this service exactly as you would using CloudFormation directly. + +For more information on the resources and properties available for this service, see the [CloudFormation documentation for AWS::KinesisVideo](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_KinesisVideo.html). + +(Read the [CDK Contributing Guide](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md) if you are interested in contributing to this construct library.) + + diff --git a/packages/@aws-cdk/aws-kinesisvideo/jest.config.js b/packages/@aws-cdk/aws-kinesisvideo/jest.config.js new file mode 100644 index 0000000000000..3a2fd93a1228a --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/jest.config.js @@ -0,0 +1,2 @@ +const baseConfig = require('@aws-cdk/cdk-build-tools/config/jest.config'); +module.exports = baseConfig; diff --git a/packages/@aws-cdk/aws-kinesisvideo/lib/index.ts b/packages/@aws-cdk/aws-kinesisvideo/lib/index.ts new file mode 100644 index 0000000000000..d5742336aa2a3 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/lib/index.ts @@ -0,0 +1,2 @@ +// AWS::KinesisVideo CloudFormation Resources: +export * from './kinesisvideo.generated'; diff --git a/packages/@aws-cdk/aws-kinesisvideo/package.json b/packages/@aws-cdk/aws-kinesisvideo/package.json new file mode 100644 index 0000000000000..6cf6f391297a3 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/package.json @@ -0,0 +1,110 @@ +{ + "name": "@aws-cdk/aws-kinesisvideo", + "version": "0.0.0", + "description": "AWS::KinesisVideo Construct Library", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "jsii": { + "outdir": "dist", + "projectReferences": true, + "targets": { + "dotnet": { + "namespace": "Amazon.CDK.AWS.KinesisVideo", + "packageId": "Amazon.CDK.AWS.KinesisVideo", + "signAssembly": true, + "assemblyOriginatorKeyFile": "../../key.snk", + "iconUrl": "https://raw.githubusercontent.com/aws/aws-cdk/master/logo/default-256-dark.png" + }, + "java": { + "package": "software.amazon.awscdk.services.kinesisvideo", + "maven": { + "groupId": "software.amazon.awscdk", + "artifactId": "kinesisvideo" + } + }, + "python": { + "classifiers": [ + "Framework :: AWS CDK", + "Framework :: AWS CDK :: 1" + ], + "distName": "aws-cdk.aws-kinesisvideo", + "module": "aws_cdk.aws_kinesisvideo" + } + }, + "metadata": { + "jsii": { + "rosetta": { + "strict": true + } + } + } + }, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-cdk.git", + "directory": "packages/@aws-cdk/aws-kinesisvideo" + }, + "homepage": "https://github.com/aws/aws-cdk", + "scripts": { + "build": "cdk-build", + "watch": "cdk-watch", + "lint": "cdk-lint", + "test": "cdk-test", + "integ": "cdk-integ", + "pkglint": "pkglint -f", + "package": "cdk-package", + "awslint": "cdk-awslint", + "cfn2ts": "cfn2ts", + "build+test": "yarn build && yarn test", + "build+test+package": "yarn build+test && yarn package", + "compat": "cdk-compat", + "gen": "cfn2ts", + "rosetta:extract": "yarn --silent jsii-rosetta extract", + "build+extract": "yarn build && yarn rosetta:extract", + "build+test+extract": "yarn build+test && yarn rosetta:extract" + }, + "cdk-build": { + "cloudformation": "AWS::KinesisVideo", + "jest": true, + "env": { + "AWSLINT_BASE_CONSTRUCT": "true" + } + }, + "keywords": [ + "aws", + "cdk", + "constructs", + "AWS::KinesisVideo", + "aws-kinesisvideo" + ], + "author": { + "name": "Amazon Web Services", + "url": "https://aws.amazon.com", + "organization": true + }, + "license": "Apache-2.0", + "devDependencies": { + "@aws-cdk/assertions": "0.0.0", + "@aws-cdk/cdk-build-tools": "0.0.0", + "@aws-cdk/cfn2ts": "0.0.0", + "@aws-cdk/pkglint": "0.0.0", + "@types/jest": "^27.4.0" + }, + "dependencies": { + "@aws-cdk/core": "0.0.0" + }, + "peerDependencies": { + "@aws-cdk/core": "0.0.0" + }, + "engines": { + "node": ">= 10.13.0 <13 || >=13.7.0" + }, + "stability": "experimental", + "maturity": "cfn-only", + "awscdkio": { + "announce": false + }, + "publishConfig": { + "tag": "latest" + } +} diff --git a/packages/@aws-cdk/aws-kinesisvideo/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-kinesisvideo/rosetta/default.ts-fixture new file mode 100644 index 0000000000000..e208762bca03c --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/rosetta/default.ts-fixture @@ -0,0 +1,8 @@ +import { Construct } from 'constructs'; +import { Stack } from '@aws-cdk/core'; + +class MyStack extends Stack { + constructor(scope: Construct, id: string) { + /// here + } +} diff --git a/packages/@aws-cdk/aws-kinesisvideo/test/kinesisvideo.test.ts b/packages/@aws-cdk/aws-kinesisvideo/test/kinesisvideo.test.ts new file mode 100644 index 0000000000000..465c7bdea0693 --- /dev/null +++ b/packages/@aws-cdk/aws-kinesisvideo/test/kinesisvideo.test.ts @@ -0,0 +1,6 @@ +import '@aws-cdk/assertions'; +import {} from '../lib'; + +test('No tests are specified for this package', () => { + expect(true).toBe(true); +}); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index a04da732aa4ae..a9a64704b6be9 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -71,14 +71,14 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-ec2": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", "delay": "5.0.0", - "esbuild": "^0.14.10" + "esbuild": "^0.14.11" }, "dependencies": { "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts index 01b90d89dd6dd..f197bb34b60da 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/function.test.ts @@ -1,7 +1,6 @@ -import '@aws-cdk/assert-internal/jest'; import * as fs from 'fs'; import * as path from 'path'; -import { ABSENT } from '@aws-cdk/assert-internal'; +import { Template, Match } from '@aws-cdk/assertions'; import { Vpc } from '@aws-cdk/aws-ec2'; import { CodeConfig, Runtime } from '@aws-cdk/aws-lambda'; import { Stack } from '@aws-cdk/core'; @@ -40,7 +39,7 @@ test('NodejsFunction with .ts handler', () => { entry: expect.stringContaining('function.test.handler1.ts'), // Automatically finds .ts handler file })); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.handler', Runtime: 'nodejs14.x', }); @@ -155,7 +154,7 @@ test('configures connection reuse for aws sdk', () => { // WHEN new NodejsFunction(stack, 'handler1'); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Environment: { Variables: { AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1', @@ -170,8 +169,8 @@ test('can opt-out of connection reuse for aws sdk', () => { awsSdkConnectionReuse: false, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { - Environment: ABSENT, + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { + Environment: Match.absent(), }); }); @@ -183,7 +182,7 @@ test('NodejsFunction in a VPC', () => { new NodejsFunction(stack, 'handler1', { vpc }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { VpcConfig: { SecurityGroupIds: [ { diff --git a/packages/@aws-cdk/aws-logs-destinations/package.json b/packages/@aws-cdk/aws-logs-destinations/package.json index e8c1455b1920e..ceb9c5c120499 100644 --- a/packages/@aws-cdk/aws-logs-destinations/package.json +++ b/packages/@aws-cdk/aws-logs-destinations/package.json @@ -64,7 +64,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-logs-destinations/test/kinesis.test.ts b/packages/@aws-cdk/aws-logs-destinations/test/kinesis.test.ts index 42c87261d60b2..4325993406ccd 100644 --- a/packages/@aws-cdk/aws-logs-destinations/test/kinesis.test.ts +++ b/packages/@aws-cdk/aws-logs-destinations/test/kinesis.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as kinesis from '@aws-cdk/aws-kinesis'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; @@ -18,13 +18,13 @@ test('stream can be subscription destination', () => { }); // THEN: subscription target is Stream - expect(stack).toHaveResource('AWS::Logs::SubscriptionFilter', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::SubscriptionFilter', { DestinationArn: { 'Fn::GetAtt': ['MyStream5C050E93', 'Arn'] }, RoleArn: { 'Fn::GetAtt': ['SubscriptionCloudWatchLogsCanPutRecords9C1223EC', 'Arn'] }, }); // THEN: we have a role to write to the Stream - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Version: '2012-10-17', Statement: [{ @@ -44,7 +44,7 @@ test('stream can be subscription destination', () => { }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -88,13 +88,13 @@ test('stream can be subscription destination twice, without duplicating permissi }); // THEN: subscription target is Stream - expect(stack).toHaveResource('AWS::Logs::SubscriptionFilter', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::SubscriptionFilter', { DestinationArn: { 'Fn::GetAtt': ['MyStream5C050E93', 'Arn'] }, RoleArn: { 'Fn::GetAtt': ['SubscriptionCloudWatchLogsCanPutRecords9C1223EC', 'Arn'] }, }); // THEN: we have a role to write to the Stream - expect(stack).toHaveResource('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Version: '2012-10-17', Statement: [{ @@ -114,7 +114,7 @@ test('stream can be subscription destination twice, without duplicating permissi }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ diff --git a/packages/@aws-cdk/aws-logs-destinations/test/lambda.test.ts b/packages/@aws-cdk/aws-logs-destinations/test/lambda.test.ts index b1f0048716a74..f5a80285c8146 100644 --- a/packages/@aws-cdk/aws-logs-destinations/test/lambda.test.ts +++ b/packages/@aws-cdk/aws-logs-destinations/test/lambda.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; @@ -28,12 +28,12 @@ test('lambda can be used as metric subscription destination', () => { }); // THEN: subscription target is Lambda - expect(stack).toHaveResource('AWS::Logs::SubscriptionFilter', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::SubscriptionFilter', { DestinationArn: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, }); // THEN: Lambda has permissions to be invoked by CWL - expect(stack).toHaveResource('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, Principal: 'logs.amazonaws.com', @@ -55,14 +55,14 @@ test('can have multiple subscriptions use the same Lambda', () => { }); // THEN: Lambda has permissions to be invoked by CWL from both Source Arns - expect(stack).toHaveResource('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, SourceArn: { 'Fn::GetAtt': ['LogGroupF5B46931', 'Arn'] }, Principal: 'logs.amazonaws.com', }); - expect(stack).toHaveResource('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, SourceArn: { 'Fn::GetAtt': ['LG224A94C8F', 'Arn'] }, @@ -79,14 +79,14 @@ test('lambda permissions are not added when addPermissions is false', () => { }); // THEN: subscription target is Lambda - expect(stack).toHaveResource('AWS::Logs::SubscriptionFilter', { + Template.fromStack(stack).hasResourceProperties('AWS::Logs::SubscriptionFilter', { DestinationArn: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, }); // THEN: Lambda does not have permissions to be invoked by CWL - expect(stack).not.toHaveResource('AWS::Lambda::Permission', { + expect(Template.fromStack(stack).findResources('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['MyLambdaCCE802FB', 'Arn'] }, Principal: 'logs.amazonaws.com', - }); + })).toEqual({}); }); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-logs/package.json b/packages/@aws-cdk/aws-logs/package.json index 1dcdd1d5920b1..1bee0d473345d 100644 --- a/packages/@aws-cdk/aws-logs/package.json +++ b/packages/@aws-cdk/aws-logs/package.json @@ -90,7 +90,7 @@ "aws-sdk": "^2.848.0", "aws-sdk-mock": "^5.5.1", "jest": "^27.4.7", - "nock": "^13.2.1", + "nock": "^13.2.2", "sinon": "^9.2.4" }, "dependencies": { diff --git a/packages/@aws-cdk/aws-neptune/README.md b/packages/@aws-cdk/aws-neptune/README.md index 57ecabab058be..c4f131b27d550 100644 --- a/packages/@aws-cdk/aws-neptune/README.md +++ b/packages/@aws-cdk/aws-neptune/README.md @@ -125,3 +125,17 @@ const replica1 = new neptune.DatabaseInstance(this, 'Instance', { instanceType: neptune.InstanceType.R5_LARGE }); ``` + +## Automatic minor version upgrades + +By setting `autoMinorVersionUpgrade` to true, Neptune will automatically update +the engine of the entire cluster to the latest minor version after a stabilization +window of 2 to 3 weeks. + +```ts +new neptune.DatabaseCluster(stack, 'Cluster', { + vpc, + instanceType: InstanceType.R5_LARGE, + autoMinorVersionUpgrade: true + }); +``` diff --git a/packages/@aws-cdk/aws-neptune/lib/cluster.ts b/packages/@aws-cdk/aws-neptune/lib/cluster.ts index cf5245d33c476..2a33f4e4629fa 100644 --- a/packages/@aws-cdk/aws-neptune/lib/cluster.ts +++ b/packages/@aws-cdk/aws-neptune/lib/cluster.ts @@ -226,6 +226,14 @@ export interface DatabaseClusterProps { * @default - Retain cluster. */ readonly removalPolicy?: RemovalPolicy + + /** + * If set to true, Neptune will automatically update the engine of the entire + * cluster to the latest minor version after a stabilization window of 2 to 3 weeks. + * + * @default - false + */ + readonly autoMinorVersionUpgrade?: boolean; } /** @@ -513,6 +521,7 @@ export class DatabaseCluster extends DatabaseClusterBase implements IDatabaseClu // Instance properties dbInstanceClass: props.instanceType._instanceType, dbParameterGroupName: props.parameterGroup?.parameterGroupName, + autoMinorVersionUpgrade: props.autoMinorVersionUpgrade === true, }); // We must have a dependency on the NAT gateway provider here to create diff --git a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts index f53af7911dc6c..e4318d5521028 100644 --- a/packages/@aws-cdk/aws-neptune/test/cluster.test.ts +++ b/packages/@aws-cdk/aws-neptune/test/cluster.test.ts @@ -523,6 +523,46 @@ describe('DatabaseCluster', () => { // THEN expect(() => { cluster.grantConnect(role); }).toThrow(/Cannot grant connect when IAM authentication is disabled/); }); + + test('autoMinorVersionUpgrade is enabled when configured', () => { + + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Cluster', { + vpc, + instanceType: InstanceType.R5_LARGE, + autoMinorVersionUpgrade: true, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { + AutoMinorVersionUpgrade: true, + }); + + }); + + test('autoMinorVersionUpgrade is not enabled when not configured', () => { + + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Cluster', { + vpc, + instanceType: InstanceType.R5_LARGE, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Neptune::DBInstance', { + AutoMinorVersionUpgrade: false, + }); + + }); + }); function testStack() { diff --git a/packages/@aws-cdk/aws-neptune/test/integ.cluster.expected.json b/packages/@aws-cdk/aws-neptune/test/integ.cluster.expected.json index 823f7af2a5b45..36a69ceec62c9 100644 --- a/packages/@aws-cdk/aws-neptune/test/integ.cluster.expected.json +++ b/packages/@aws-cdk/aws-neptune/test/integ.cluster.expected.json @@ -491,7 +491,8 @@ "DBInstanceClass": "db.r5.large", "DBClusterIdentifier": { "Ref": "DatabaseB269D8BB" - } + }, + "AutoMinorVersionUpgrade": true }, "DependsOn": [ "VPCPrivateSubnet1DefaultRouteAE1D6490", diff --git a/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts b/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts index b62c0d054a624..2a29ebe2cc1c2 100644 --- a/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts +++ b/packages/@aws-cdk/aws-neptune/test/integ.cluster.ts @@ -35,6 +35,7 @@ class TestStack extends cdk.Stack { clusterParameterGroup: params, kmsKey, removalPolicy: cdk.RemovalPolicy.DESTROY, + autoMinorVersionUpgrade: true, }); cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); diff --git a/packages/@aws-cdk/aws-opensearchservice/lib/version.ts b/packages/@aws-cdk/aws-opensearchservice/lib/version.ts index f170504c17338..119b7844502dc 100644 --- a/packages/@aws-cdk/aws-opensearchservice/lib/version.ts +++ b/packages/@aws-cdk/aws-opensearchservice/lib/version.ts @@ -62,6 +62,9 @@ export class EngineVersion { /** AWS OpenSearch 1.0 */ public static readonly OPENSEARCH_1_0 = EngineVersion.openSearch('1.0'); + /** AWS OpenSearch 1.1 */ + public static readonly OPENSEARCH_1_1 = EngineVersion.openSearch('1.1'); + /** * Custom ElasticSearch version * @param version custom version number diff --git a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts index fa1068025c657..d8d5c91f41507 100644 --- a/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/cluster-engine.ts @@ -334,6 +334,8 @@ export class AuroraMysqlEngineVersion { public static readonly VER_2_09_1 = AuroraMysqlEngineVersion.builtIn_5_7('2.09.1'); /** Version "5.7.mysql_aurora.2.09.2". */ public static readonly VER_2_09_2 = AuroraMysqlEngineVersion.builtIn_5_7('2.09.2'); + /** Version "5.7.mysql_aurora.2.09.3". */ + public static readonly VER_2_09_3 = AuroraMysqlEngineVersion.builtIn_5_7('2.09.3'); /** Version "5.7.mysql_aurora.2.10.0". */ public static readonly VER_2_10_0 = AuroraMysqlEngineVersion.builtIn_5_7('2.10.0'); /** Version "5.7.mysql_aurora.2.10.1". */ diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index 5b2388eb35b45..310d071ec226b 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -1392,7 +1392,10 @@ export class SqlServerEngineVersion { public static readonly VER_14_00_3035_2_V1 = SqlServerEngineVersion.of('14.00.3035.2.v1', '14.00'); /** Version "14.00.3049.1.v1". */ public static readonly VER_14_00_3049_1_V1 = SqlServerEngineVersion.of('14.00.3049.1.v1', '14.00'); - /** Version "14.00.3192.2.v1". */ + /** + * Version "14.00.3192.2.v1". + * @deprecated SQL Server version 14.00.3192.2.v1 reached end of life + */ public static readonly VER_14_00_3192_2_V1 = SqlServerEngineVersion.of('14.00.3192.2.v1', '14.00'); /** Version "14.00.3223.3.v1". */ public static readonly VER_14_00_3223_3_V1 = SqlServerEngineVersion.of('14.00.3223.3.v1', '14.00'); diff --git a/packages/@aws-cdk/aws-s3-assets/package.json b/packages/@aws-cdk/aws-s3-assets/package.json index 489749cfee25e..80996d4ebc255 100644 --- a/packages/@aws-cdk/aws-s3-assets/package.json +++ b/packages/@aws-cdk/aws-s3-assets/package.json @@ -77,7 +77,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cloud-assembly-schema": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts b/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts index 7a335ab3b7bb2..f04218f95929d 100644 --- a/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts +++ b/packages/@aws-cdk/aws-s3-assets/test/asset.test.ts @@ -1,12 +1,11 @@ -import { ResourcePart, SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { Match, Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cdk from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; import { Asset } from '../lib/asset'; const SAMPLE_ASSET_DIR = path.join(__dirname, 'sample-asset-directory'); @@ -79,7 +78,7 @@ test('"file" assets', () => { expect(entry).toBeTruthy(); // synthesize first so "prepare" is called - const template = SynthUtils.synthesize(stack).template; + const template = Template.fromStack(stack); expect(stack.resolve(entry!.data)).toEqual({ path: 'asset.78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197.txt', @@ -92,8 +91,12 @@ test('"file" assets', () => { }); // verify that now the template contains parameters for this asset - expect(template.Parameters.AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3Bucket2C60F94A.Type).toBe('String'); - expect(template.Parameters.AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3VersionKey9482DC35.Type).toBe('String'); + expect(template.findParameters('AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3Bucket2C60F94A') + .AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3Bucket2C60F94A.Type) + .toBe('String'); + expect(template.findParameters('AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3VersionKey9482DC35') + .AssetParameters78add9eaf468dfa2191da44a7da92a21baba4c686cf6053d772556768ef21197S3VersionKey9482DC35.Type) + .toBe('String'); }); test('"readers" or "grantRead" can be used to grant read permissions on the asset to a principal', () => { @@ -108,7 +111,7 @@ test('"readers" or "grantRead" can be used to grant read permissions on the asse asset.grantRead(group); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Version: '2012-10-17', Statement: [ @@ -200,13 +203,13 @@ test('addResourceMetadata can be used to add CFN metadata to resources', () => { asset.addResourceMetadata(resource, 'PropName'); // THEN - expect(stack).toHaveResource('My::Resource::Type', { + Template.fromStack(stack).hasResource('My::Resource::Type', { Metadata: { 'aws:asset:path': 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }, - }, ResourcePart.CompleteDefinition); + }); }); test('asset metadata is only emitted if ASSET_RESOURCE_METADATA_ENABLED_CONTEXT is defined', () => { @@ -220,13 +223,13 @@ test('asset metadata is only emitted if ASSET_RESOURCE_METADATA_ENABLED_CONTEXT asset.addResourceMetadata(resource, 'PropName'); // THEN - expect(stack).not.toHaveResource('My::Resource::Type', { + Template.fromStack(stack).hasResource('My::Resource::Type', Match.not({ Metadata: { 'aws:asset:path': SAMPLE_ASSET_DIR, 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', }, - }, ResourcePart.CompleteDefinition); + })); }); test('nested assemblies share assets: legacy synth edition', () => { @@ -350,8 +353,8 @@ describe('staging', () => { // WHEN asset.addResourceMetadata(resource, 'PropName'); - const template = SynthUtils.synthesize(stack).template; - expect(template.Resources.MyResource.Metadata).toEqual({ + const template = Template.fromStack(stack); + expect(template.findResources('My::Resource::Type').MyResource.Metadata).toEqual({ 'aws:asset:path': 'asset.6b84b87243a4a01c592d78e1fd3855c4bfef39328cd0a450cc97e81717fea2a2', 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', @@ -377,8 +380,8 @@ describe('staging', () => { // WHEN asset.addResourceMetadata(resource, 'PropName'); - const template = SynthUtils.synthesize(stack).template; - expect(template.Resources.MyResource.Metadata).toEqual({ + const template = Template.fromStack(stack); + expect(template.findResources('My::Resource::Type').MyResource.Metadata).toEqual({ 'aws:asset:path': SAMPLE_ASSET_DIR, 'aws:asset:is-bundled': false, 'aws:asset:property': 'PropName', diff --git a/packages/@aws-cdk/aws-s3-deployment/README.md b/packages/@aws-cdk/aws-s3-deployment/README.md index f9bff70495c1d..1b86bb4fa92e4 100644 --- a/packages/@aws-cdk/aws-s3-deployment/README.md +++ b/packages/@aws-cdk/aws-s3-deployment/README.md @@ -9,8 +9,6 @@ -> __Status: Experimental__ - This library allows populating an S3 bucket with the contents of .zip files from other S3 buckets or from local disk. @@ -278,12 +276,14 @@ new s3deploy.BucketDeployment(this, 'DeployMeWithEfsStorage', { which can be deployed into the bucket by this timeout. - When the `BucketDeployment` is removed from the stack, the contents are retained in the destination bucket ([#952](https://github.com/aws/aws-cdk/issues/952)). -- Bucket deployment _only happens_ during stack create/update. This means that - if you wish to update the contents of the destination, you will need to - change the source s3 key (or bucket), so that the resource will be updated. - This is inline with best practices. If you use local disk assets, this will - happen automatically whenever you modify the asset, since the S3 key is based - on a hash of the asset contents. +- If you are using `s3deploy.Source.bucket()` to take the file source from + another bucket: the deployed files will only be updated if the key (file name) + of the file in the source bucket changes. Mutating the file in place will not + be good enough: the custom resource will simply not run if the properties don't + change. + - If you use assets (`s3deploy.Source.asset()`) you don't need to worry + about this: the asset system will make sure that if the files have changed, + the file name is unique and the deployment will run. ## Development diff --git a/packages/@aws-cdk/aws-s3-deployment/package.json b/packages/@aws-cdk/aws-s3-deployment/package.json index aa967f81e56c4..70adaaac2ff88 100644 --- a/packages/@aws-cdk/aws-s3-deployment/package.json +++ b/packages/@aws-cdk/aws-s3-deployment/package.json @@ -85,7 +85,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cx-api": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts index 38023cc0154e6..9507cdb5dace7 100644 --- a/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/@aws-cdk/aws-s3-deployment/test/bucket-deployment.test.ts @@ -1,6 +1,5 @@ import * as path from 'path'; -import { MatchStyle, objectLike } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as cloudfront from '@aws-cdk/aws-cloudfront'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; @@ -27,7 +26,7 @@ test('deploy from local directory asset', () => { }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { ServiceToken: { 'Fn::GetAtt': [ 'CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536', @@ -89,7 +88,7 @@ test('deploy with configured log retention', () => { }); // THEN - expect(stack).toHaveResourceLike('Custom::LogRetention', { RetentionInDays: 7 }); + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { RetentionInDays: 7 }); }); test('deploy from local directory assets', () => { @@ -107,7 +106,7 @@ test('deploy from local directory assets', () => { }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { ServiceToken: { 'Fn::GetAtt': [ 'CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536', @@ -235,7 +234,7 @@ test('deploy from a local .zip file when efs is enabled', () => { }); //THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Environment: { Variables: { MOUNT_PATH: '/mnt/lambda', @@ -315,7 +314,7 @@ testDeprecated('honors passed asset options', () => { }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { ServiceToken: { 'Fn::GetAtt': [ 'CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536', @@ -377,7 +376,7 @@ test('retainOnDelete can be used to retain files when resource is deleted', () = }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { RetainOnDelete: true, }); }); @@ -398,7 +397,7 @@ test('user metadata is correctly transformed', () => { }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { UserMetadata: { a: '1', b: '2' }, }); }); @@ -427,7 +426,7 @@ test('system metadata is correctly transformed', () => { }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { SystemMetadata: { 'content-type': 'text/html', 'content-language': 'en', @@ -472,7 +471,7 @@ test.each(Object.entries(accessControlMap) as [s3.BucketAccessControl, string][] }); // THEN - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { SystemMetadata: { acl: systemMetadataKeyword, }, @@ -537,7 +536,7 @@ test('distribution can be used to provide a CloudFront distribution for invalida distributionPaths: ['/images/*'], }); - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { DistributionId: { Ref: 'DistributionCFDistribution882A7313', }, @@ -567,7 +566,7 @@ test('invalidation can happen without distributionPaths provided', () => { distribution, }); - expect(stack).toHaveResource('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { DistributionId: { Ref: 'DistributionCFDistribution882A7313', }, @@ -626,7 +625,7 @@ testFutureBehavior('lambda execution role gets permissions to read from the sour }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -735,9 +734,9 @@ test('memoryLimit can be used to specify the memory limit for the deployment res // we expect to find only two handlers, one for each configuration - expect(stack).toCountResources('AWS::Lambda::Function', 2); - expect(stack).toHaveResource('AWS::Lambda::Function', { MemorySize: 256 }); - expect(stack).toHaveResource('AWS::Lambda::Function', { MemorySize: 1024 }); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 2); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { MemorySize: 256 }); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { MemorySize: 1024 }); }); test('deployment allows custom role to be supplied', () => { @@ -757,9 +756,9 @@ test('deployment allows custom role to be supplied', () => { }); // THEN - expect(stack).toCountResources('AWS::IAM::Role', 1); - expect(stack).toCountResources('AWS::Lambda::Function', 1); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 1); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 1); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'Role1ABCC5F0', @@ -782,7 +781,7 @@ test('deploy without deleting missing files from destination', () => { prune: false, }); - expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { Prune: false, }); }); @@ -799,7 +798,7 @@ test('deploy with excluded files from destination', () => { exclude: ['sample.js'], }); - expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { Exclude: ['sample.js'], }); }); @@ -817,7 +816,7 @@ test('deploy with included files from destination', () => { include: ['sample.js'], }); - expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { Include: ['sample.js'], }); }); @@ -836,7 +835,7 @@ test('deploy with excluded and included files from destination', () => { include: ['sample/include.json'], }); - expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { Exclude: ['sample/*'], Include: ['sample/include.json'], }); @@ -856,7 +855,7 @@ test('deploy with multiple exclude and include filters', () => { include: ['sample/include.json', 'another/include.json'], }); - expect(stack).toHaveResourceLike('Custom::CDKBucketDeployment', { + Template.fromStack(stack).hasResourceProperties('Custom::CDKBucketDeployment', { Exclude: ['sample/*', 'another/*'], Include: ['sample/include.json', 'another/include.json'], }); @@ -877,7 +876,7 @@ test('deployment allows vpc to be implicitly supplied to lambda', () => { }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { VpcConfig: { SecurityGroupIds: [ { @@ -922,7 +921,7 @@ test('deployment allows vpc and subnets to be implicitly supplied to lambda', () }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { VpcConfig: { SecurityGroupIds: [ { @@ -957,13 +956,13 @@ test('resource id includes memory and vpc', () => { }); // THEN - expect(stack).toMatchTemplate({ - Resources: objectLike({ - DeployWithVpc2CustomResource256MiBc8a39596cb8641929fcf6a288bc9db5ab7b0f656ad3C5F6E78: objectLike({ + Template.fromStack(stack).templateMatches({ + Resources: Match.objectLike({ + DeployWithVpc2CustomResource256MiBc8a39596cb8641929fcf6a288bc9db5ab7b0f656ad3C5F6E78: Match.objectLike({ Type: 'Custom::CDKBucketDeployment', }), }), - }, MatchStyle.SUPERSET); + }); }); test('bucket includes custom resource owner tag', () => { @@ -983,7 +982,7 @@ test('bucket includes custom resource owner tag', () => { }); // THEN - expect(stack).toHaveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { Tags: [{ Key: 'aws-cdk:cr-owned:/a/b/c:971e1fa8', Value: 'true', @@ -1040,7 +1039,7 @@ test('bucket has multiple deployments', () => { }); // THEN - expect(stack).toHaveResource('AWS::S3::Bucket', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { Tags: [ { Key: 'aws-cdk:cr-owned:/a/b/c:6da0a4ab', diff --git a/packages/@aws-cdk/aws-s3-notifications/package.json b/packages/@aws-cdk/aws-s3-notifications/package.json index 3723da0f32e79..f40467d02c99d 100644 --- a/packages/@aws-cdk/aws-s3-notifications/package.json +++ b/packages/@aws-cdk/aws-s3-notifications/package.json @@ -71,7 +71,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/aws-s3-notifications/test/lambda/lambda.test.ts b/packages/@aws-cdk/aws-s3-notifications/test/lambda/lambda.test.ts index 4d80618ad8ff3..d6e563a4438ca 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/lambda/lambda.test.ts +++ b/packages/@aws-cdk/aws-s3-notifications/test/lambda/lambda.test.ts @@ -1,6 +1,4 @@ -// import { SynthUtils } from '@aws-cdk/assert-internal'; -import { ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as lambda from '@aws-cdk/aws-lambda'; import * as s3 from '@aws-cdk/aws-s3'; import { Stack, App } from '@aws-cdk/core'; @@ -29,20 +27,20 @@ test('add notifications to multiple functions', () => { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination2, { prefix: 'v2/' }); // expecting notification configuration to have both events - expect(stack).toHaveResourceLike('Custom::S3BucketNotifications', { - NotificationConfiguration: { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { + NotificationConfiguration: Match.objectLike({ LambdaFunctionConfigurations: [ - { Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v1/' }] } } }, - { Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v2/' }] } } }, + Match.objectLike({ Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v1/' }] } } }), + Match.objectLike({ Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v2/' }] } } }), ], - }, + }), }); // expecting one permission for each function - expect(stack).toCountResources('AWS::Lambda::Permission', 2); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Permission', 2); // make sure each permission points to the correct function - expect(stack).toHaveResourceLike('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { FunctionName: { 'Fn::GetAtt': [ 'MyFunction12A744C2E', @@ -56,7 +54,7 @@ test('add notifications to multiple functions', () => { ], }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { FunctionName: { 'Fn::GetAtt': [ 'MyFunction2F2A964CA', @@ -89,7 +87,7 @@ test('lambda in a different stack as notification target', () => { bucket.addObjectCreatedNotification(new s3n.LambdaDestination(lambdaFunction)); // permission should be in the bucket stack - expect(bucketStack).toHaveResourceLike('AWS::Lambda::Permission', { + Template.fromStack(bucketStack).hasResourceProperties('AWS::Lambda::Permission', { FunctionName: { 'Fn::ImportValue': 'stack1:ExportsOutputFnGetAttlambdaFunction940E68ADArn6B2878AF', }, @@ -115,7 +113,7 @@ test('imported lambda in a different account as notification target', () => { bucket.addObjectCreatedNotification(new s3n.LambdaDestination(lambdaFunction)); // no permissions created - expect(stack).not.toHaveResourceLike('AWS::Lambda::Permission'); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Permission', 0); }); test('lambda as notification target', () => { @@ -132,7 +130,7 @@ test('lambda as notification target', () => { bucketA.addObjectCreatedNotification(new s3n.LambdaDestination(fn), { suffix: '.png' }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': ['MyFunction3BAA72D1', 'Arn'] }, Principal: 's3.amazonaws.com', @@ -140,7 +138,7 @@ test('lambda as notification target', () => { SourceArn: { 'Fn::GetAtt': ['MyBucketF68F3FF0', 'Arn'] }, }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { NotificationConfiguration: { LambdaFunctionConfigurations: [ { @@ -167,7 +165,7 @@ test('lambda as notification target specified by function arn', () => { bucketA.addObjectCreatedNotification(new s3n.LambdaDestination(fn), { suffix: '.png' }); // THEN - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { NotificationConfiguration: { LambdaFunctionConfigurations: [ { @@ -199,9 +197,9 @@ test('permissions are added as a dependency to the notifications resource when u bucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination, { prefix: 'v1/' }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResource('Custom::S3BucketNotifications', { DependsOn: ['MyBucketAllowBucketNotificationsToSingletonLambdauuid28C96883'], - }, ResourcePart.CompleteDefinition); + }); }); test('add multiple event notifications using a singleton function', () => { @@ -220,13 +218,13 @@ test('add multiple event notifications using a singleton function', () => { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination, { prefix: 'v1/' }); bucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaDestination, { prefix: 'v2/' }); - expect(stack).toHaveResourceLike('Custom::S3BucketNotifications', { - NotificationConfiguration: { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { + NotificationConfiguration: Match.objectLike({ LambdaFunctionConfigurations: [ - { Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v1/' }] } } }, - { Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v2/' }] } } }, + Match.objectLike({ Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v1/' }] } } }), + Match.objectLike({ Filter: { Key: { FilterRules: [{ Name: 'prefix', Value: 'v2/' }] } } }), ], - }, + }), }); }); diff --git a/packages/@aws-cdk/aws-s3-notifications/test/notifications.test.ts b/packages/@aws-cdk/aws-s3-notifications/test/notifications.test.ts index 2bfe968f99279..ee4cbc9c5c5d0 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/notifications.test.ts +++ b/packages/@aws-cdk/aws-s3-notifications/test/notifications.test.ts @@ -1,5 +1,4 @@ -import { SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as s3 from '@aws-cdk/aws-s3'; import * as sns from '@aws-cdk/aws-sns'; import * as cdk from '@aws-cdk/core'; @@ -13,7 +12,7 @@ test('bucket without notifications', () => { new s3.Bucket(stack, 'MyBucket'); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'MyBucketF68F3FF0': { 'Type': 'AWS::S3::Bucket', @@ -33,7 +32,7 @@ test('notifications can be added to imported buckets', () => { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SnsDestination(topic)); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { ServiceToken: { 'Fn::GetAtt': ['BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691', 'Arn'] }, BucketName: 'mybucket', Managed: false, @@ -61,9 +60,9 @@ test('when notification are added, a custom resource is provisioned + a lambda h bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SnsDestination(topic)); - expect(stack).toHaveResource('AWS::S3::Bucket'); - expect(stack).toHaveResource('AWS::Lambda::Function', { Description: 'AWS CloudFormation handler for "Custom::S3BucketNotifications" resources (@aws-cdk/aws-s3)' }); - expect(stack).toHaveResource('Custom::S3BucketNotifications'); + Template.fromStack(stack).resourceCountIs('AWS::S3::Bucket', 1); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Description: 'AWS CloudFormation handler for "Custom::S3BucketNotifications" resources (@aws-cdk/aws-s3)' }); + Template.fromStack(stack).resourceCountIs('Custom::S3BucketNotifications', 1); }); test('when notification are added, you can tag the lambda', () => { @@ -76,12 +75,12 @@ test('when notification are added, you can tag the lambda', () => { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.SnsDestination(topic)); - expect(stack).toHaveResource('AWS::S3::Bucket'); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).resourceCountIs('AWS::S3::Bucket', 1); + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Tags: [{ Key: 'Lambda', Value: 'AreTagged' }], Description: 'AWS CloudFormation handler for "Custom::S3BucketNotifications" resources (@aws-cdk/aws-s3)', }); - expect(stack).toHaveResource('Custom::S3BucketNotifications'); + Template.fromStack(stack).resourceCountIs('Custom::S3BucketNotifications', 1); }); test('bucketNotificationTarget is not called during synthesis', () => { @@ -95,7 +94,7 @@ test('bucketNotificationTarget is not called during synthesis', () => { bucket.addObjectCreatedNotification(new s3n.SnsDestination(topic)); - expect(stack).toHaveResourceLike('AWS::SNS::TopicPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::SNS::TopicPolicy', { 'Topics': [ { 'Ref': 'TopicBFC7AF6E', @@ -122,6 +121,7 @@ test('bucketNotificationTarget is not called during synthesis', () => { 'Resource': { 'Ref': 'TopicBFC7AF6E', }, + 'Sid': '0', }, ], 'Version': '2012-10-17', @@ -159,7 +159,7 @@ test('subscription types', () => { bucket.addEventNotification(s3.EventType.OBJECT_CREATED, lambdaTarget); bucket.addObjectRemovedNotification(topicTarget, { prefix: 'prefix' }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { 'ServiceToken': { 'Fn::GetAtt': [ 'BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691', @@ -227,7 +227,7 @@ test('multiple subscriptions of the same type', () => { }), }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { 'ServiceToken': { 'Fn::GetAtt': [ 'BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691', @@ -268,7 +268,7 @@ test('prefix/suffix filters', () => { bucket.addEventNotification(s3.EventType.OBJECT_REMOVED_DELETE, { bind: _ => bucketNotificationTarget }, { prefix: 'images/', suffix: '.jpg' }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { 'ServiceToken': { 'Fn::GetAtt': [ 'BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691', @@ -320,7 +320,7 @@ test('a notification destination can specify a set of dependencies that must be bucket.addObjectCreatedNotification(dest); - expect(SynthUtils.synthesize(stack).template.Resources.BucketNotifications8F2E257D).toEqual({ + expect(Template.fromStack(stack).findResources('Custom::S3BucketNotifications').BucketNotifications8F2E257D).toEqual({ Type: 'Custom::S3BucketNotifications', Properties: { ServiceToken: { 'Fn::GetAtt': ['BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691', 'Arn'] }, @@ -344,7 +344,7 @@ describe('CloudWatch Events', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { 'EventPattern': { 'source': [ 'aws.s3', @@ -387,7 +387,7 @@ describe('CloudWatch Events', () => { paths: ['my/path.zip'], }); - expect(stack).toHaveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { 'EventPattern': { 'source': [ 'aws.s3', @@ -429,7 +429,7 @@ describe('CloudWatch Events', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { 'EventPattern': { 'source': [ 'aws.s3', @@ -457,7 +457,7 @@ describe('CloudWatch Events', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { 'EventPattern': { 'source': [ 'aws.s3', @@ -485,7 +485,7 @@ describe('CloudWatch Events', () => { paths: ['my/path.zip'], }); - expect(stack).toHaveResourceLike('AWS::Events::Rule', { + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { 'EventPattern': { 'source': [ 'aws.s3', diff --git a/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts b/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts index 22c2edac592c8..b1ae15e895a7c 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts +++ b/packages/@aws-cdk/aws-s3-notifications/test/queue.test.ts @@ -1,5 +1,4 @@ -import { arrayWith, SynthUtils } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as s3 from '@aws-cdk/aws-s3'; import * as sqs from '@aws-cdk/aws-sqs'; import { Stack } from '@aws-cdk/core'; @@ -13,7 +12,7 @@ test('queues can be used as destinations', () => { bucket.addObjectRemovedNotification(new notif.SqsDestination(queue)); - expect(stack).toHaveResource('AWS::SQS::QueuePolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::SQS::QueuePolicy', { PolicyDocument: { Statement: [ { @@ -44,7 +43,7 @@ test('queues can be used as destinations', () => { ], }); - expect(stack).toHaveResource('Custom::S3BucketNotifications', { + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { BucketName: { Ref: 'Bucket83908E77', }, @@ -67,7 +66,11 @@ test('queues can be used as destinations', () => { // make sure the queue policy is added as a dependency to the bucket // notifications resource so it will be created first. - expect(SynthUtils.synthesize(stack).template.Resources.BucketNotifications8F2E257D.DependsOn).toEqual(['QueuePolicy25439813', 'Queue4A7E3555']); + + const resources = Template.fromStack(stack).findResources('Custom::S3BucketNotifications'); + + expect(resources.BucketNotifications8F2E257D.DependsOn) + .toEqual(['QueuePolicy25439813', 'Queue4A7E3555']); }); test('if the queue is encrypted with a custom kms key, the key resource policy is updated to allow s3 to read messages', () => { @@ -77,9 +80,9 @@ test('if the queue is encrypted with a custom kms key, the key resource policy i bucket.addObjectCreatedNotification(new notif.SqsDestination(queue)); - expect(stack).toHaveResourceLike('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: [ 'kms:GenerateDataKey*', 'kms:Decrypt', @@ -89,7 +92,7 @@ test('if the queue is encrypted with a custom kms key, the key resource policy i Service: 's3.amazonaws.com', }, Resource: '*', - }), + }]), }, }); }); diff --git a/packages/@aws-cdk/aws-s3-notifications/test/sns.test.ts b/packages/@aws-cdk/aws-s3-notifications/test/sns.test.ts index 2c91becaae188..8a1d607113059 100644 --- a/packages/@aws-cdk/aws-s3-notifications/test/sns.test.ts +++ b/packages/@aws-cdk/aws-s3-notifications/test/sns.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as s3 from '@aws-cdk/aws-s3'; import * as sns from '@aws-cdk/aws-sns'; import * as cdk from '@aws-cdk/core'; @@ -16,7 +16,7 @@ test('asBucketNotificationDestination adds bucket permissions only once for each // another bucket will be added to the topic policy new notif.SnsDestination(topic).bind(bucket2, bucket2); - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ Resources: { Bucket83908E77: { Type: 'AWS::S3::Bucket', diff --git a/packages/@aws-cdk/aws-s3/lib/bucket.ts b/packages/@aws-cdk/aws-s3/lib/bucket.ts index 15e69d4610a70..387139d718ffb 100644 --- a/packages/@aws-cdk/aws-s3/lib/bucket.ts +++ b/packages/@aws-cdk/aws-s3/lib/bucket.ts @@ -1886,6 +1886,7 @@ export class Bucket extends BucketBase { noncurrentVersionTransitions: mapOrUndefined(rule.noncurrentVersionTransitions, t => ({ storageClass: t.storageClass.value, transitionInDays: t.transitionAfter.toDays(), + newerNoncurrentVersions: t.noncurrentVersionsToRetain, })), prefix: rule.prefix, status: enabled ? 'Enabled' : 'Disabled', diff --git a/packages/@aws-cdk/aws-s3/lib/rule.ts b/packages/@aws-cdk/aws-s3/lib/rule.ts index bd9492c44ab84..5ce32ba7ed798 100644 --- a/packages/@aws-cdk/aws-s3/lib/rule.ts +++ b/packages/@aws-cdk/aws-s3/lib/rule.ts @@ -151,6 +151,13 @@ export interface NoncurrentVersionTransition { * @default No transition count. */ readonly transitionAfter: Duration; + + /** + * Indicates the number of noncurrent version objects to be retained. Can be up to 100 noncurrent versions retained. + * + * @default No noncurrent version retained. + */ + readonly noncurrentVersionsToRetain?: number; } /** diff --git a/packages/@aws-cdk/aws-s3/test/rules.test.ts b/packages/@aws-cdk/aws-s3/test/rules.test.ts index 8f2a39cb4fa99..4adf00e4b3441 100644 --- a/packages/@aws-cdk/aws-s3/test/rules.test.ts +++ b/packages/@aws-cdk/aws-s3/test/rules.test.ts @@ -139,4 +139,76 @@ describe('rules', () => { }, }); }); + + test('Noncurrent transistion rule with versions to retain', () => { + // GIVEN + const stack = new Stack(); + + // WHEN: Noncurrent version to retain available + new Bucket(stack, 'Bucket1', { + versioned: true, + lifecycleRules: [{ + noncurrentVersionExpiration: Duration.days(10), + noncurrentVersionTransitions: [ + { + storageClass: StorageClass.GLACIER_INSTANT_RETRIEVAL, + transitionAfter: Duration.days(10), + noncurrentVersionsToRetain: 1, + }, + ], + }], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { + LifecycleConfiguration: { + Rules: [{ + NoncurrentVersionExpirationInDays: 10, + NoncurrentVersionTransitions: [ + { + NewerNoncurrentVersions: 1, + StorageClass: 'GLACIER_IR', + TransitionInDays: 10, + }, + ], + Status: 'Enabled', + }], + }, + }); + }); + + test('Noncurrent transistion rule without versions to retain', () => { + // GIVEN + const stack = new Stack(); + + // WHEN: Noncurrent version to retain not set + new Bucket(stack, 'Bucket1', { + versioned: true, + lifecycleRules: [{ + noncurrentVersionExpiration: Duration.days(10), + noncurrentVersionTransitions: [ + { + storageClass: StorageClass.GLACIER_INSTANT_RETRIEVAL, + transitionAfter: Duration.days(10), + }, + ], + }], + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { + LifecycleConfiguration: { + Rules: [{ + NoncurrentVersionExpirationInDays: 10, + NoncurrentVersionTransitions: [ + { + StorageClass: 'GLACIER_IR', + TransitionInDays: 10, + }, + ], + Status: 'Enabled', + }], + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts index cc51f4b009d26..81e8fa2f4ca81 100644 --- a/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts +++ b/packages/@aws-cdk/aws-secretsmanager/lib/secret.ts @@ -1,6 +1,6 @@ import * as iam from '@aws-cdk/aws-iam'; import * as kms from '@aws-cdk/aws-kms'; -import { ArnFormat, FeatureFlags, Fn, IResource, Lazy, RemovalPolicy, Resource, SecretValue, Stack, Token } from '@aws-cdk/core'; +import { ArnFormat, FeatureFlags, Fn, IResource, Lazy, RemovalPolicy, Resource, SecretValue, Stack, Token, TokenComparison } from '@aws-cdk/core'; import * as cxapi from '@aws-cdk/cx-api'; import { IConstruct, Construct } from 'constructs'; import { ResourcePolicy } from './policy'; @@ -306,8 +306,10 @@ abstract class SecretBase extends Resource implements ISecret { ); } + const crossAccount = Token.compareStrings(Stack.of(this).account, grantee.grantPrincipal.principalAccount || ''); + // Throw if secret is not imported and it's shared cross account and no KMS key is provided - if (this instanceof Secret && result.resourceStatement && !this.encryptionKey) { + if (this instanceof Secret && result.resourceStatement && (!this.encryptionKey && crossAccount === TokenComparison.DIFFERENT)) { throw new Error('KMS Key must be provided for cross account access to Secret'); } diff --git a/packages/@aws-cdk/aws-secretsmanager/test/secret.test.ts b/packages/@aws-cdk/aws-secretsmanager/test/secret.test.ts index 66ec71c497474..0068a8d46652e 100644 --- a/packages/@aws-cdk/aws-secretsmanager/test/secret.test.ts +++ b/packages/@aws-cdk/aws-secretsmanager/test/secret.test.ts @@ -267,6 +267,46 @@ describe('secretStringBeta1', () => { }); test('grantRead', () => { + // GIVEN + const secret = new secretsmanager.Secret(stack, 'Secret'); + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountRootPrincipal() }); + + // WHEN + secret.grantRead(role); + + // THEN + expect(stack).toHaveResource('AWS::IAM::Policy', { + PolicyDocument: { + Version: '2012-10-17', + Statement: [{ + Action: [ + 'secretsmanager:GetSecretValue', + 'secretsmanager:DescribeSecret', + ], + Effect: 'Allow', + Resource: { Ref: 'SecretA720EF05' }, + }], + }, + }); +}); + +test('Error when grantRead with different role and no KMS', () => { + // GIVEN + const testStack = new cdk.Stack(app, 'TestStack', { + env: { + account: '123456789012', + }, + }); + const secret = new secretsmanager.Secret(testStack, 'Secret'); + const role = iam.Role.fromRoleArn(testStack, 'RoleFromArn', 'arn:aws:iam::111111111111:role/SomeRole'); + + // THEN + expect(() => { + secret.grantRead(role); + }).toThrowError('KMS Key must be provided for cross account access to Secret'); +}); + +test('grantRead with KMS Key', () => { // GIVEN const key = new kms.Key(stack, 'KMS'); const secret = new secretsmanager.Secret(stack, 'Secret', { encryptionKey: key }); diff --git a/packages/@aws-cdk/aws-ses-actions/package.json b/packages/@aws-cdk/aws-ses-actions/package.json index 1c41d8f7333b0..2d42ecb26c71b 100644 --- a/packages/@aws-cdk/aws-ses-actions/package.json +++ b/packages/@aws-cdk/aws-ses-actions/package.json @@ -65,7 +65,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-ses-actions/test/actions.test.ts b/packages/@aws-cdk/aws-ses-actions/test/actions.test.ts index 4a425fd51f76b..845f99c963aa7 100644 --- a/packages/@aws-cdk/aws-ses-actions/test/actions.test.ts +++ b/packages/@aws-cdk/aws-ses-actions/test/actions.test.ts @@ -1,5 +1,4 @@ -import { arrayWith, ResourcePart } from '@aws-cdk/assert-internal'; -import '@aws-cdk/assert-internal/jest'; +import { Match, Template } from '@aws-cdk/assertions'; import * as kms from '@aws-cdk/aws-kms'; import * as lambda from '@aws-cdk/aws-lambda'; import * as s3 from '@aws-cdk/aws-s3'; @@ -25,7 +24,7 @@ test('add header action', () => { value: 'value', })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Actions: [ { @@ -62,7 +61,7 @@ test('add bounce action', () => { topic, })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Actions: [ { @@ -95,7 +94,7 @@ test('add lambda action', () => { topic, })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResource('AWS::SES::ReceiptRule', { Properties: { Rule: { Actions: [ @@ -123,9 +122,9 @@ test('add lambda action', () => { DependsOn: [ 'FunctionAllowSes1829904A', ], - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::Lambda::Permission', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Permission', { Action: 'lambda:InvokeFunction', FunctionName: { 'Fn::GetAtt': [ @@ -151,7 +150,7 @@ test('add s3 action', () => { topic, })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResource('AWS::SES::ReceiptRule', { Properties: { Rule: { Actions: [ @@ -182,9 +181,9 @@ test('add s3 action', () => { DependsOn: [ 'BucketPolicyE9A3008A', ], - }, ResourcePart.CompleteDefinition); + }); - expect(stack).toHaveResource('AWS::S3::BucketPolicy', { + Template.fromStack(stack).hasResourceProperties('AWS::S3::BucketPolicy', { Bucket: { Ref: 'Bucket83908E77', }, @@ -223,9 +222,9 @@ test('add s3 action', () => { }, }); - expect(stack).toHaveResourceLike('AWS::KMS::Key', { + Template.fromStack(stack).hasResourceProperties('AWS::KMS::Key', { KeyPolicy: { - Statement: arrayWith({ + Statement: Match.arrayWith([{ Action: [ 'kms:Encrypt', 'kms:GenerateDataKey', @@ -246,7 +245,7 @@ test('add s3 action', () => { Service: 'ses.amazonaws.com', }, Resource: '*', - }), + }]), }, }); }); @@ -257,7 +256,7 @@ test('add sns action', () => { topic, })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Actions: [ { @@ -279,7 +278,7 @@ test('add stop action', () => { topic, })); - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Actions: [ { diff --git a/packages/@aws-cdk/aws-ses/package.json b/packages/@aws-cdk/aws-ses/package.json index 134bc98d95365..64ad0fc5f67ce 100644 --- a/packages/@aws-cdk/aws-ses/package.json +++ b/packages/@aws-cdk/aws-ses/package.json @@ -79,7 +79,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-ses/test/receipt-filter.test.ts b/packages/@aws-cdk/aws-ses/test/receipt-filter.test.ts index 69e966555d0a9..74e6dc8742340 100644 --- a/packages/@aws-cdk/aws-ses/test/receipt-filter.test.ts +++ b/packages/@aws-cdk/aws-ses/test/receipt-filter.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { AllowListReceiptFilter, ReceiptFilter, ReceiptFilterPolicy } from '../lib'; @@ -17,7 +17,7 @@ describe('receipt filter', () => { }); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'FilterC907D6DA': { 'Type': 'AWS::SES::ReceiptFilter', @@ -50,7 +50,7 @@ describe('receipt filter', () => { }); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'AllowListBlockAll094C9B97': { 'Type': 'AWS::SES::ReceiptFilter', diff --git a/packages/@aws-cdk/aws-ses/test/receipt-rule-set.test.ts b/packages/@aws-cdk/aws-ses/test/receipt-rule-set.test.ts index a80886c442144..0386b71f39425 100644 --- a/packages/@aws-cdk/aws-ses/test/receipt-rule-set.test.ts +++ b/packages/@aws-cdk/aws-ses/test/receipt-rule-set.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { ReceiptRuleSet } from '../lib'; @@ -15,7 +15,7 @@ describe('receipt rule set', () => { }); // THEN - expect(stack).toHaveResource('AWS::SES::ReceiptRuleSet', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRuleSet', { RuleSetName: 'MyRuleSet', }); @@ -32,7 +32,7 @@ describe('receipt rule set', () => { }); // THEN - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Actions: [ { @@ -52,7 +52,7 @@ describe('receipt rule set', () => { }, }); - expect(stack).toHaveResource('AWS::Lambda::Function'); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 1); }); @@ -73,7 +73,7 @@ describe('receipt rule set', () => { }); // THEN - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { Rule: { Enabled: true, Recipients: [ @@ -87,7 +87,7 @@ describe('receipt rule set', () => { }, }); - expect(stack).toHaveResource('AWS::Lambda::Function'); + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 1); }); @@ -102,7 +102,7 @@ describe('receipt rule set', () => { receiptRuleSet.addRule('MyRule'); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'ImportedRuleSetMyRule53EE2F7F': { 'Type': 'AWS::SES::ReceiptRule', diff --git a/packages/@aws-cdk/aws-ses/test/receipt-rule.test.ts b/packages/@aws-cdk/aws-ses/test/receipt-rule.test.ts index 4cb86efe88b72..d8a3805cee858 100644 --- a/packages/@aws-cdk/aws-ses/test/receipt-rule.test.ts +++ b/packages/@aws-cdk/aws-ses/test/receipt-rule.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Stack } from '@aws-cdk/core'; import { ReceiptRule, ReceiptRuleSet, TlsPolicy } from '../lib'; @@ -26,7 +26,7 @@ describe('receipt rule', () => { }); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'RuleSetE30C6C48': { 'Type': 'AWS::SES::ReceiptRuleSet', @@ -82,7 +82,7 @@ describe('receipt rule', () => { }); // THEN - expect(stack).toMatchTemplate({ + Template.fromStack(stack).templateMatches({ 'Resources': { 'RuleSetE30C6C48': { 'Type': 'AWS::SES::ReceiptRuleSet', @@ -124,7 +124,7 @@ describe('receipt rule', () => { }); // THEN - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { 'Rule': { 'Actions': [ { @@ -159,7 +159,7 @@ describe('receipt rule', () => { }); // THEN - expect(stack).toHaveResource('AWS::SES::ReceiptRule', { + Template.fromStack(stack).hasResourceProperties('AWS::SES::ReceiptRule', { 'Rule': { 'Actions': [ { diff --git a/packages/@aws-cdk/aws-signer/package.json b/packages/@aws-cdk/aws-signer/package.json index 93cb08670772c..064c381b6a88a 100644 --- a/packages/@aws-cdk/aws-signer/package.json +++ b/packages/@aws-cdk/aws-signer/package.json @@ -74,7 +74,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/aws-signer/test/signing-profile.test.ts b/packages/@aws-cdk/aws-signer/test/signing-profile.test.ts index 49ada5da2f596..44db183b565a5 100644 --- a/packages/@aws-cdk/aws-signer/test/signing-profile.test.ts +++ b/packages/@aws-cdk/aws-signer/test/signing-profile.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; import * as signer from '../lib'; @@ -14,7 +14,7 @@ describe('signing profile', () => { const platform = signer.Platform.AWS_LAMBDA_SHA384_ECDSA; new signer.SigningProfile( stack, 'SigningProfile', { platform } ); - expect(stack).toHaveResource('AWS::Signer::SigningProfile', { + Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { PlatformId: platform.platformId, SignatureValidityPeriod: { Type: 'MONTHS', @@ -30,7 +30,7 @@ describe('signing profile', () => { signatureValidity: cdk.Duration.days( 7 ), } ); - expect(stack).toHaveResource('AWS::Signer::SigningProfile', { + Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { PlatformId: platform.platformId, SignatureValidityPeriod: { Type: 'DAYS', @@ -47,7 +47,7 @@ describe('signing profile', () => { cdk.Tags.of(signing).add('tag2', 'value2'); cdk.Tags.of(signing).add('tag3', ''); - expect(stack).toHaveResource('AWS::Signer::SigningProfile', { + Template.fromStack(stack).hasResourceProperties('AWS::Signer::SigningProfile', { PlatformId: platform.platformId, SignatureValidityPeriod: { Type: 'MONTHS', @@ -109,7 +109,7 @@ describe('signing profile', () => { ], ], }); - expect(stack).toMatchTemplate({}); + Template.fromStack(stack).templateMatches({}); }); } ); }); diff --git a/packages/@aws-cdk/aws-stepfunctions/README.md b/packages/@aws-cdk/aws-stepfunctions/README.md index e74367df84676..eae413c7c3574 100644 --- a/packages/@aws-cdk/aws-stepfunctions/README.md +++ b/packages/@aws-cdk/aws-stepfunctions/README.md @@ -485,9 +485,9 @@ The class `StateMachineFragment` contains some helper functions (like machine as a subclass of this, it will be convenient to use: ```ts nofixture -import { Construct, Stack } from '@aws-cdk/core'; +import { Stack } from '@aws-cdk/core'; +import { Construct } from 'constructs'; import * as sfn from '@aws-cdk/aws-stepfunctions'; -import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; interface MyJobProps { jobFlavor: string; @@ -515,10 +515,14 @@ class MyStack extends Stack { constructor(scope: Construct, id: string) { super(scope, id); // Do 3 different variants of MyJob in parallel - new sfn.Parallel(this, 'All jobs') + const parallel = new sfn.Parallel(this, 'All jobs') .branch(new MyJob(this, 'Quick', { jobFlavor: 'quick' }).prefixStates()) .branch(new MyJob(this, 'Medium', { jobFlavor: 'medium' }).prefixStates()) .branch(new MyJob(this, 'Slow', { jobFlavor: 'slow' }).prefixStates()); + + new sfn.StateMachine(this, 'MyStateMachine', { + definition: parallel, + }); } } ``` diff --git a/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture b/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture index 91085b6c8933c..01f59d49ec36d 100644 --- a/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/aws-stepfunctions/rosetta/default.ts-fixture @@ -1,10 +1,10 @@ // Fixture with packages imported, but nothing else import { Construct } from 'constructs'; import { App, CfnOutput, Duration, Stack } from '@aws-cdk/core'; -import sfn = require('@aws-cdk/aws-stepfunctions'); -import tasks = require('@aws-cdk/aws-stepfunctions-tasks'); -import cloudwatch = require('@aws-cdk/aws-cloudwatch'); -import iam = require('@aws-cdk/aws-iam'); +import * as sfn from '@aws-cdk/aws-stepfunctions'; +import * as tasks from '@aws-cdk/aws-stepfunctions-tasks'; +import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; +import * as iam from '@aws-cdk/aws-iam'; class Fixture extends Stack { constructor(scope: Construct, id: string) { diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 4f3775440e943..9d2b6815ee159 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,4 +1,234 @@ +## Unapplied changes + +* AWS::ECS is at 51.0.0 +* AWS::SageMaker is at 51.0.0 + + +## Unapplied changes + +* AWS::ECS is at 51.0.0 +* AWS::SageMaker is at 51.0.0 + +# CloudFormation Resource Specification v53.0.0 + +## New Resource Types + +* AWS::AppStream::ApplicationEntitlementAssociation +* AWS::AppStream::Entitlement +* AWS::EC2::NetworkInsightsAccessScope +* AWS::EC2::NetworkInsightsAccessScopeAnalysis +* AWS::Forecast::Dataset +* AWS::Forecast::DatasetGroup +* AWS::InspectorV2::Filter +* AWS::KinesisVideo::SignalingChannel +* AWS::KinesisVideo::Stream +* AWS::Lightsail::Alarm +* AWS::Lightsail::Bucket +* AWS::Lightsail::LoadBalancer +* AWS::Lightsail::LoadBalancerTlsCertificate + +## Attribute Changes + +* AWS::EC2::Host HostId (__added__) +* AWS::EC2::IPAMScope IpamScopeType (__added__) +* AWS::EC2::VPNGatewayRoutePropagation Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html +* AWS::EC2::VPNGatewayRoutePropagation Id (__added__) +* AWS::IoTAnalytics::Channel Id (__added__) +* AWS::IoTAnalytics::Dataset Id (__added__) +* AWS::IoTAnalytics::Datastore Id (__added__) +* AWS::RDS::DBProxy VpcId (__deleted__) +* AWS::Redshift::EventSubscription EventCategoriesList.DuplicatesAllowed (__added__) + +## Property Changes + +* AWS::AppSync::FunctionConfiguration MaxBatchSize (__added__) +* AWS::AppSync::Resolver MaxBatchSize (__added__) +* AWS::AutoScaling::WarmPool InstanceReusePolicy (__added__) +* AWS::Config::OrganizationConfigRule OrganizationCustomCodeRuleMetadata (__added__) +* AWS::EC2::ClientVpnEndpoint ClientLoginBannerOptions (__added__) +* AWS::EC2::ClientVpnEndpoint SessionTimeoutHours (__added__) +* AWS::EC2::FlowLog DestinationOptions (__added__) +* AWS::EC2::IPAMScope IpamScopeType (__deleted__) +* AWS::EC2::VPNGatewayRoutePropagation RouteTableIds.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html#cfn-ec2-vpngatewayrouteprop-routetableids + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html#cfn-ec2-vpngatewayroutepropagation-routetableids +* AWS::EC2::VPNGatewayRoutePropagation VpnGatewayId.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html#cfn-ec2-vpngatewayrouteprop-vpngatewayid + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html#cfn-ec2-vpngatewayroutepropagation-vpngatewayid +* AWS::Events::EventBus Tags (__added__) +* AWS::GameLift::GameSessionQueue Tags (__added__) +* AWS::GameLift::MatchmakingConfiguration Tags (__added__) +* AWS::GameLift::MatchmakingRuleSet Tags (__added__) +* AWS::GameLift::Script Tags (__added__) +* AWS::IoT::JobTemplate JobExecutionsRetryConfig (__added__) +* AWS::IoTAnalytics::Channel Tags.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset Actions.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset ContentDeliveryRules.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset LateDataRules.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset Tags.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset Triggers.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Datastore Tags.DuplicatesAllowed (__added__) +* AWS::RUM::AppMonitor Domain.Required (__changed__) + * Old: false + * New: true +* AWS::RUM::AppMonitor Name.Required (__changed__) + * Old: false + * New: true +* AWS::Redshift::EventSubscription EventCategories.DuplicatesAllowed (__added__) + +## Property Type Changes + +* AWS::KinesisAnalyticsV2::Application.CustomArtifactsConfiguration (__removed__) +* AWS::AutoScaling::WarmPool.InstanceReusePolicy (__added__) +* AWS::Config::OrganizationConfigRule.OrganizationCustomCodeRuleMetadata (__added__) +* AWS::EC2::ClientVpnEndpoint.ClientLoginBannerOptions (__added__) +* AWS::EC2::LaunchTemplate.InstanceRequirements (__added__) +* AWS::Events::EventBus.TagEntry (__added__) +* AWS::Glue::Crawler.MongoDBTarget (__added__) +* AWS::IoTSiteWise::Gateway.GreengrassV2 (__added__) +* AWS::NimbleStudio::LaunchProfile.StreamConfigurationSessionStorage (__added__) +* AWS::NimbleStudio::LaunchProfile.StreamingSessionStorageRoot (__added__) +* AWS::AppSync::Resolver.CachingConfig Ttl.Required (__changed__) + * Old: false + * New: true +* AWS::EC2::LaunchTemplate.LaunchTemplateData InstanceRequirements (__added__) +* AWS::Glue::Crawler.S3Target DlqEventQueueArn (__added__) +* AWS::Glue::Crawler.S3Target EventQueueArn (__added__) +* AWS::Glue::Crawler.S3Target SampleSize (__added__) +* AWS::Glue::Crawler.Targets MongoDBTargets (__added__) +* AWS::IoTAnalytics::Dataset.ContainerAction Variables.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset.DatasetContentVersionValue DatasetName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-datasetcontentversionvalue.html#cfn-iotanalytics-dataset-variable-datasetcontentversionvalue-datasetname + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-datasetcontentversionvalue.html#cfn-iotanalytics-dataset-datasetcontentversionvalue-datasetname +* AWS::IoTAnalytics::Dataset.DatasetContentVersionValue DatasetName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Dataset.OutputFileUriValue FileName.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-outputfileurivalue.html#cfn-iotanalytics-dataset-variable-outputfileurivalue-filename + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-outputfileurivalue.html#cfn-iotanalytics-dataset-outputfileurivalue-filename +* AWS::IoTAnalytics::Dataset.OutputFileUriValue FileName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Dataset.QueryAction Filters.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Dataset.Schedule ScheduleExpression.Documentation (__changed__) + * Old: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-trigger-schedule.html#cfn-iotanalytics-dataset-trigger-schedule-scheduleexpression + * New: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-schedule.html#cfn-iotanalytics-dataset-schedule-scheduleexpression +* AWS::IoTAnalytics::Datastore.DatastorePartitions Partitions.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Datastore.IotSiteWiseMultiLayerStorage CustomerManagedS3Storage.Required (__changed__) + * Old: true + * New: false +* AWS::IoTAnalytics::Datastore.SchemaDefinition Columns.DuplicatesAllowed (__added__) +* AWS::IoTAnalytics::Pipeline.AddAttributes Attributes.PrimitiveType (__deleted__) +* AWS::IoTAnalytics::Pipeline.AddAttributes Attributes.PrimitiveItemType (__added__) +* AWS::IoTAnalytics::Pipeline.AddAttributes Attributes.Type (__added__) +* AWS::IoTAnalytics::Pipeline.AddAttributes Attributes.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.AddAttributes Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Channel ChannelName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Channel Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Datastore DatastoreName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Datastore Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceRegistryEnrich Attribute.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceRegistryEnrich Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceRegistryEnrich RoleArn.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceRegistryEnrich ThingName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceShadowEnrich Attribute.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceShadowEnrich Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceShadowEnrich RoleArn.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.DeviceShadowEnrich ThingName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Filter Filter.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Filter Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Lambda BatchSize.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Lambda LambdaName.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Lambda Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Math Attribute.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Math Math.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.Math Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.RemoveAttributes Attributes.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.RemoveAttributes Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.SelectAttributes Attributes.Required (__changed__) + * Old: false + * New: true +* AWS::IoTAnalytics::Pipeline.SelectAttributes Name.Required (__changed__) + * Old: false + * New: true +* AWS::IoTSiteWise::Gateway.GatewayPlatform GreengrassV2 (__added__) +* AWS::IoTSiteWise::Gateway.GatewayPlatform Greengrass.Required (__changed__) + * Old: true + * New: false +* AWS::KinesisAnalyticsV2::Application.ZeppelinApplicationConfiguration CustomArtifactsConfiguration.ItemType (__added__) +* AWS::KinesisAnalyticsV2::Application.ZeppelinApplicationConfiguration CustomArtifactsConfiguration.Type (__changed__) + * Old: CustomArtifactsConfiguration + * New: List +* AWS::Lex::BotAlias.BotAliasLocaleSettingsItem BotAliasLocaleSetting.Required (__changed__) + * Old: false + * New: true +* AWS::Lex::BotAlias.BotAliasLocaleSettingsItem LocaleId.Required (__changed__) + * Old: false + * New: true +* AWS::Lex::BotAlias.TextLogDestination CloudWatch.Type (__added__) +* AWS::MediaLive::Channel.HlsGroupSettings ProgramDateTimeClock (__added__) +* AWS::MediaLive::Channel.InputSettings Scte35Pid (__added__) +* AWS::NimbleStudio::LaunchProfile.StreamConfiguration MaxStoppedSessionLengthInMinutes (__added__) +* AWS::NimbleStudio::LaunchProfile.StreamConfiguration SessionStorage (__added__) +* AWS::Transfer::Server.ProtocolDetails TlsSessionResumptionMode (__added__) + +## Unapplied changes + +* AWS::ECS is at 51.0.0 +* AWS::SageMaker is at 51.0.0 + + # Serverless Application Model (SAM) Resource Specification v2016-10-31 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts b/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts index 656d5ae16a53b..8d06fe1148967 100644 --- a/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts +++ b/packages/@aws-cdk/cfnspec/build-tools/create-missing-libraries.ts @@ -21,7 +21,9 @@ async function main() { } // eslint-disable-next-line @typescript-eslint/no-require-imports - const version = require('../package.json').version; + const cfnSpecPkgJson = require('../package.json'); + const version = cfnSpecPkgJson.version; + const jestTypesVersion = cfnSpecPkgJson.devDependencies['@types/jest']; // iterate over all cloudformation namespaces for (const namespace of cfnspec.namespaces()) { @@ -172,7 +174,7 @@ async function main() { '@aws-cdk/cdk-build-tools': version, '@aws-cdk/cfn2ts': version, '@aws-cdk/pkglint': version, - '@types/jest': '^26.0.22', + '@types/jest': jestTypesVersion, }, dependencies: { '@aws-cdk/core': version, diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 92837e4d8f0cc..b0fa2fdea909c 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -51.0.0 +53.0.0 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 1be4360363dcc..5b6f0ce4d8f0c 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 @@ -512,7 +512,7 @@ "properties": { "AccessToken": "Personal Access token for 3rd party source control system for an Amplify app, used to create webhook and read-only deploy key. Token is not stored.\n\n*Length Constraints:* Minimum length of 1. Maximum length of 255.", "AutoBranchCreationConfig": "Sets the configuration for your automatic branch creation.", - "BasicAuthConfig": "The credentials for basic authorization for an Amplify app.", + "BasicAuthConfig": "The credentials for basic authorization for an Amplify app. You must base64-encode the authorization credentials and provide them in the format `user:password` .", "BuildSpec": "The build specification (build spec) for an Amplify app.\n\n*Length Constraints:* Minimum length of 1. Maximum length of 25000.\n\n*Pattern:* (?s).+", "CustomHeaders": "The custom HTTP headers for an Amplify app.\n\n*Length Constraints:* Minimum length of 0. Maximum length of 25000.\n\n*Pattern:* (?s).*", "CustomRules": "The custom rewrite and redirect rules for an Amplify app.", @@ -577,7 +577,7 @@ "description": "The AWS::Amplify::Branch resource creates a new branch within an app.", "properties": { "AppId": "The unique ID for an Amplify app.\n\n*Length Constraints:* Minimum length of 1. Maximum length of 20.\n\n*Pattern:* d[a-z0-9]+", - "BasicAuthConfig": "The basic authorization credentials for a branch of an Amplify app.", + "BasicAuthConfig": "The basic authorization credentials for a branch of an Amplify app. You must base64-encode the authorization credentials and provide them in the format `user:password` .", "BranchName": "The name for the branch.\n\n*Length Constraints:* Minimum length of 1. Maximum length of 255.\n\n*Pattern:* (?s).+", "BuildSpec": "The build specification (build spec) for the branch.\n\n*Length Constraints:* Minimum length of 1. Maximum length of 25000.\n\n*Pattern:* (?s).+", "Description": "The description for the branch that is part of an Amplify app.\n\n*Length Constraints:* Maximum length of 1000.\n\n*Pattern:* (?s).*", @@ -4339,6 +4339,7 @@ "DataSourceName": "The name of data source this function will attach.", "Description": "The `Function` description.", "FunctionVersion": "The version of the request mapping template. Currently, only the 2018-05-29 version of the template is supported.", + "MaxBatchSize": "The maximum number of resolver request inputs that will be sent to a single AWS Lambda function in a `BatchInvoke` operation.", "Name": "The name of the function.", "RequestMappingTemplate": "The `Function` request mapping template. Functions support only the 2018-05-29 version of the request mapping template.", "RequestMappingTemplateS3Location": "Describes a Sync configuration for a resolver.\n\nContains information on which Conflict Detection, as well as Resolution strategy, should be performed when the resolver is invoked.", @@ -4475,6 +4476,7 @@ "DataSourceName": "The resolver data source name.", "FieldName": "The GraphQL field on a type that invokes the resolver.", "Kind": "The resolver type.\n\n- *UNIT* : A UNIT resolver type. A UNIT resolver is the default resolver type. You can use a UNIT resolver to run a GraphQL query against a single data source.\n- *PIPELINE* : A PIPELINE resolver type. You can use a PIPELINE resolver to invoke a series of `Function` objects in a serial manner. You can use a pipeline resolver to run a GraphQL query against multiple data sources.", + "MaxBatchSize": "The maximum number of resolver request inputs that will be sent to a single AWS Lambda function in a `BatchInvoke` operation.", "PipelineConfig": "Functions linked with the pipeline resolver.", "RequestMappingTemplate": "The request mapping template.\n\nRequest mapping templates are optional when using a Lambda data source. For all other data sources, a request mapping template is required.", "RequestMappingTemplateS3Location": "The location of a request mapping template in an Amazon S3 bucket. Use this if you want to provision with a template file in Amazon S3 rather than embedding it in your CloudFormation template.", @@ -7024,7 +7026,7 @@ "description": "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.\n\nYou cannot apply both event selectors and advanced event selectors to a trail.", "properties": { "DataResources": "CloudTrail supports data event logging for Amazon S3 objects and AWS Lambda functions. You can specify up to 250 resources for an individual event selector, but the total number of data resources cannot exceed 250 across all event selectors in a trail. This limit does not apply if you configure resource logging for all data events.\n\nFor more information, see [Data Events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-management-and-data-events-with-cloudtrail.html#logging-data-events) and [Limits in AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/WhatIsCloudTrail-Limits.html) in the *AWS CloudTrail User Guide* .", - "ExcludeManagementEventSources": "An optional list of service event sources from which you do not want management events to be logged on your trail. In this release, the list can be empty (disables the filter), or it can filter out AWS Key Management Service or Amazon RDS Data API events by containing `kms.amazonaws.com` or `rdsdata.amazonaws.com` . By default, `ExcludeManagementEventSources` is empty, and AWS KMS and Amazon RDS Data API events are logged to your trail.", + "ExcludeManagementEventSources": "An optional list of service event sources from which you do not want management events to be logged on your trail. In this release, the list can be empty (disables the filter), or it can filter out AWS Key Management Service or Amazon RDS Data API events by containing `kms.amazonaws.com` or `rdsdata.amazonaws.com` . By default, `ExcludeManagementEventSources` is empty, and AWS KMS and Amazon RDS Data API events are logged to your trail. You can exclude management event sources only in regions that support the event source.", "IncludeManagementEvents": "Specify if you want your event selector to include management events for your trail.\n\nFor more information, see [Management Events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-management-and-data-events-with-cloudtrail.html#logging-management-events) in the *AWS CloudTrail User Guide* .\n\nBy default, the value is `true` .\n\nThe first copy of management events is free. You are charged for additional copies of management events that you are logging on any subsequent trail in the same region. For more information about CloudTrail pricing, see [AWS CloudTrail Pricing](https://docs.aws.amazon.com/cloudtrail/pricing/) .", "ReadWriteType": "Specify if you want your trail to log read-only events, write-only events, or all. For example, the EC2 `GetConsoleOutput` is a read-only API operation and `RunInstances` is a write-only API operation.\n\nBy default, the value is `All` ." } @@ -11360,8 +11362,8 @@ "IpamId": "The ID of the IPAM.", "PrivateDefaultScopeId": "The ID of the IPAM's default private scope.", "PublicDefaultScopeId": "The ID of the IPAM's default public scope.", - "Ref": "", - "ScopeCount": "The number of scopes in the IPAM." + "Ref": "`Ref` returns the IPAM ID.", + "ScopeCount": "The number of scopes in the IPAM. The scope quota is 5." }, "description": "IPAM is a VPC feature that you can use to automate your IP address management workflows including assigning, tracking, troubleshooting, and auditing IP addresses across AWS Regions and accounts throughout your AWS Organization. For more information, see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", "properties": { @@ -11379,27 +11381,27 @@ }, "AWS::EC2::IPAMAllocation": { "attributes": { - "IpamPoolAllocationId": "The ID of the allocation.", - "Ref": "" + "IpamPoolAllocationId": "The ID of an allocation.", + "Ref": "`Ref` returns the pool ID, allocation ID, and CIDR." }, - "description": "", + "description": "In IPAM, an allocation is a CIDR assignment from an IPAM pool to another resource or IPAM pool.", "properties": { "Cidr": "The CIDR you would like to allocate from the IPAM pool. Note the following:\n\n- If there is no DefaultNetmaskLength allocation rule set on the pool, you must specify either the NetmaskLength or the CIDR.\n- If the DefaultNetmaskLength allocation rule is set on the pool, you can specify either the NetmaskLength or the CIDR and the DefaultNetmaskLength allocation rule will be ignored.\n\nPossible values: Any available IPv4 or IPv6 CIDR.", - "Description": "A description of the pool allocation.", + "Description": "A description for the allocation.", "IpamPoolId": "The ID of the IPAM pool from which you would like to allocate a CIDR.", "NetmaskLength": "The netmask length of the CIDR you would like to allocate from the IPAM pool. Note the following:\n\n- If there is no DefaultNetmaskLength allocation rule set on the pool, you must specify either the NetmaskLength or the CIDR.\n- If the DefaultNetmaskLength allocation rule is set on the pool, you can specify either the NetmaskLength or the CIDR and the DefaultNetmaskLength allocation rule will be ignored.\n\nPossible netmask lengths for IPv4 addresses are 0 - 32. Possible netmask lengths for IPv6 addresses are 0 - 128." } }, "AWS::EC2::IPAMPool": { "attributes": { - "Arn": "The ARN of the IPAM.", - "IpamArn": "The ARN of the IPAM pool.", + "Arn": "The ARN of the IPAM pool.", + "IpamArn": "The ARN of the IPAM.", "IpamPoolId": "The ID of the IPAM pool.", "IpamScopeArn": "The ARN of the scope of the IPAM pool.", - "IpamScopeType": "The IPAM scope type (public | private).", - "PoolDepth": "The depth of pools in your IPAM pool.", - "Ref": "", - "State": "The state of the IPAM pool (create-in-progress | create-complete | create-failed | modify-in-progress | modify-complete | modify-failed | delete-in-progress | delete-complete | delete-failed).", + "IpamScopeType": "The scope of the IPAM.", + "PoolDepth": "The depth of pools in your IPAM pool. The pool depth quota is 10.", + "Ref": "`Ref` returns the IPAM pool ID.", + "State": "The state of the IPAM pool.", "StateMessage": "A message related to the failed creation of an IPAM pool." }, "description": "In IPAM, a pool is a collection of contiguous IP addresses CIDRs. Pools enable you to organize your IP addresses according to your routing and security needs. For example, if you have separate routing and security needs for development and production applications, you can create a pool for each.", @@ -11411,9 +11413,9 @@ "AllocationResourceTags": "Tags that are required for resources that use CIDRs from this IPAM pool. Resources that do not have these tags will not be allowed to allocate space from the pool. If the resources have their tags changed after they have allocated space or if the allocation tagging requirements are changed on the pool, the resource may be marked as noncompliant.", "AutoImport": "If selected, IPAM will continuously look for resources within the CIDR range of this pool and automatically import them as allocations into your IPAM. The CIDRs that will be allocated for these resources must not already be allocated to other resources in order for the import to succeed. IPAM will import a CIDR regardless of its compliance with the pool's allocation rules, so a resource might be imported and subsequently marked as noncompliant. If IPAM discovers multiple CIDRs that overlap, IPAM will import the largest CIDR only. If IPAM discovers multiple CIDRs with matching CIDRs, IPAM will randomly import one of them only.\n\nA locale must be set on the pool for this feature to work.", "Description": "The description of the IPAM pool.", - "IpamScopeId": "", + "IpamScopeId": "The ID of the scope in which you would like to create the IPAM pool.", "Locale": "The locale of the IPAM pool. In IPAM, the locale is the AWS Region where you want to make an IPAM pool available for allocations. Only resources in the same Region as the locale of the pool can get IP address allocations from the pool. You can only allocate a CIDR for a VPC, for example, from an IPAM pool that shares a locale with the VPC\u2019s Region. Note that once you choose a Locale for a pool, you cannot modify it. If you choose an AWS Region for locale that has not been configured as an operating Region for the IPAM, you'll get an error.", - "ProvisionedCidrs": "", + "ProvisionedCidrs": "Information about the CIDRs provisioned to an IPAM pool.", "PubliclyAdvertisable": "Determines if a pool is publicly advertisable. This option is not available for pools with AddressFamily set to `ipv4` .", "SourceIpamPoolId": "The ID of the source IPAM pool. You can use this option to create an IPAM pool within an existing source pool.", "Tags": "The key/value combination of a tag assigned to the resource. Use the tag key in the filter name and the tag value as the filter value. For example, to find all resources that have a tag with the key `Owner` and the value `TeamA` , specify `tag:Owner` for the filter name and `TeamA` for the filter value." @@ -11421,24 +11423,24 @@ }, "AWS::EC2::IPAMPool.ProvisionedCidr": { "attributes": {}, - "description": "", + "description": "The CIDR provisioned to the IPAM pool. A CIDR is a representation of an IP address and its associated network mask (or netmask) and refers to a range of IP addresses. An IPv4 CIDR example is `10.24.34.0/23` . An IPv6 CIDR example is `2001:DB8::/32` .", "properties": { - "Cidr": "" + "Cidr": "The CIDR provisioned to the IPAM pool. A CIDR is a representation of an IP address and its associated network mask (or netmask) and refers to a range of IP addresses. An IPv4 CIDR example is `10.24.34.0/23` . An IPv6 CIDR example is `2001:DB8::/32` ." } }, "AWS::EC2::IPAMScope": { "attributes": { "Arn": "The ARN of the scope.", - "IpamArn": "The ARN of the IPAM.", - "IpamScopeId": "The ID of the scope.", - "IsDefault": "Indicates whether the scope is the default scope.", - "PoolCount": "The number of pools in the scope.", - "Ref": "" + "IpamArn": "The ARN of an IPAM.", + "IpamScopeId": "The ID of an IPAM scope.", + "IsDefault": "Defines if the scope is the default scope or not.", + "PoolCount": "The number of pools in a scope.", + "Ref": "`Ref` returns the IPAM scope ID." }, "description": "In IPAM, a scope is the highest-level container within IPAM. An IPAM contains two default scopes. Each scope represents the IP space for a single network. The private scope is intended for all private IP address space. The public scope is intended for all public IP address space. Scopes enable you to reuse IP addresses across multiple unconnected networks without causing IP address overlap or conflict.\n\nFor more information, see [How IPAM works](https://docs.aws.amazon.com//vpc/latest/ipam/how-it-works-ipam.html) in the *Amazon VPC IPAM User Guide*", "properties": { "Description": "The description of the scope.", - "IpamId": "", + "IpamId": "The ID of the IPAM for which you're creating this scope.", "IpamScopeType": "The type of the scope.", "Tags": "The key/value combination of a tag assigned to the resource. Use the tag key in the filter name and the tag value as the filter value. For example, to find all resources that have a tag with the key `Owner` and the value `TeamA` , specify `tag:Owner` for the filter name and `TeamA` for the filter value." } @@ -13198,7 +13200,7 @@ "description": "Specifies a VPC attachment.", "properties": { "AddSubnetIds": "The IDs of one or more subnets to add. You can specify at most one subnet per Availability Zone.", - "Options": "The VPC attachment options.\n\n- DnsSupport (enable | disable)\n- Ipv6Support (enable| disable)\n- ApplianceModeSupport (enable | disable)", + "Options": "The VPC attachment options in JSON or YAML.\n\n- DnsSupport (enable | disable)\n- Ipv6Support (enable| disable)\n- ApplianceModeSupport (enable | disable)", "RemoveSubnetIds": "The IDs of one or more subnets to remove.", "SubnetIds": "The IDs of the subnets.", "Tags": "The tags for the VPC attachment.", @@ -13215,14 +13217,14 @@ "Ipv6CidrBlocks": "The IPv6 CIDR blocks that are associated with the VPC, such as `[ 2001:db8:1234:1a00::/56 ]` .", "Ref": "`Ref` returns the ID of the VPC." }, - "description": "Specifies a VPC with the specified IPv4 CIDR block. The smallest VPC you can create uses a /28 netmask (16 IPv4 addresses), and the largest uses a /16 netmask (65,536 IPv4 addresses). For more information about how large to make your VPC, see [Your VPC and Subnets](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) in the *Amazon Virtual Private Cloud User Guide* .", + "description": "Specifies a VPC with the specified IPv4 CIDR block. The smallest VPC you can create uses a /28 netmask (16 IPv4 addresses), and the largest uses a /16 netmask (65,536 IPv4 addresses). For more information about how large to make your VPC, see [Overview of VPCs and subnets](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html) in the *Amazon Virtual Private Cloud User Guide* .", "properties": { "CidrBlock": "The primary IPv4 CIDR block for the VPC.", - "EnableDnsHostnames": "Indicates whether the instances launched in the VPC get DNS hostnames. If enabled, instances in the VPC get DNS hostnames; otherwise, they do not. Disabled by default for nondefault VPCs. For more information, see [DNS Support in Your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) .\n\nYou can only enable DNS hostnames if you've enabled DNS support.", - "EnableDnsSupport": "Indicates whether the DNS resolution is supported for the VPC. If enabled, queries to the Amazon provided DNS server at the 169.254.169.253 IP address, or the reserved IP address at the base of the VPC network range \"plus two\" succeed. If disabled, the Amazon provided DNS service in the VPC that resolves public DNS hostnames to IP addresses is not enabled. Enabled by default. For more information, see [DNS Support in Your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) .", + "EnableDnsHostnames": "Indicates whether the instances launched in the VPC get DNS hostnames. If enabled, instances in the VPC get DNS hostnames; otherwise, they do not. Disabled by default for nondefault VPCs. For more information, see [DNS attributes in your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) .\n\nYou can only enable DNS hostnames if you've enabled DNS support.", + "EnableDnsSupport": "Indicates whether the DNS resolution is supported for the VPC. If enabled, queries to the Amazon provided DNS server at the 169.254.169.253 IP address, or the reserved IP address at the base of the VPC network range \"plus two\" succeed. If disabled, the Amazon provided DNS service in the VPC that resolves public DNS hostnames to IP addresses is not enabled. Enabled by default. For more information, see [DNS attributes in your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-support) .", "InstanceTenancy": "The allowed tenancy of instances launched into the VPC.\n\n- `\"default\"` : An instance launched into the VPC runs on shared hardware by default, unless you explicitly specify a different tenancy during instance launch.\n- `\"dedicated\"` : An instance launched into the VPC is a Dedicated Instance by default, unless you explicitly specify a tenancy of host during instance launch. You cannot specify a tenancy of default during instance launch.\n\nUpdating `InstanceTenancy` requires no replacement only if you are updating its value from `\"dedicated\"` to `\"default\"` . Updating `InstanceTenancy` from `\"default\"` to `\"dedicated\"` requires replacement.", - "Ipv4IpamPoolId": "", - "Ipv4NetmaskLength": "", + "Ipv4IpamPoolId": "The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR. For more information, see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", + "Ipv4NetmaskLength": "The netmask length of the IPv4 CIDR you want to allocate to this VPC from an Amazon VPC IP Address Manager (IPAM) pool. For more information about IPAM, see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", "Tags": "The tags for the VPC." } }, @@ -13234,11 +13236,11 @@ "properties": { "AmazonProvidedIpv6CidrBlock": "Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IPv6 addresses, or the size of the CIDR block.", "CidrBlock": "An IPv4 CIDR block to associate with the VPC.", - "Ipv4IpamPoolId": "", - "Ipv4NetmaskLength": "", + "Ipv4IpamPoolId": "Associate a CIDR allocated from an IPv4 IPAM pool to a VPC. For more information about Amazon VPC IP Address Manager (IPAM), see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", + "Ipv4NetmaskLength": "The netmask length of the IPv4 CIDR you would like to associate from an Amazon VPC IP Address Manager (IPAM) pool. For more information about IPAM, see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", "Ipv6CidrBlock": "An IPv6 CIDR block from the IPv6 address pool. You must also specify `Ipv6Pool` in the request.\n\nTo let Amazon choose the IPv6 CIDR block for you, omit this parameter.", - "Ipv6IpamPoolId": "", - "Ipv6NetmaskLength": "", + "Ipv6IpamPoolId": "Associates a CIDR allocated from an IPv6 IPAM pool to a VPC. For more information about Amazon VPC IP Address Manager (IPAM), see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", + "Ipv6NetmaskLength": "The netmask length of the IPv6 CIDR you would like to associate from an Amazon VPC IP Address Manager (IPAM) pool. For more information about IPAM, see [What is IPAM?](https://docs.aws.amazon.com//vpc/latest/ipam/what-is-it-ipam.html) in the *Amazon VPC IPAM User Guide* .", "Ipv6Pool": "The ID of an IPv6 address pool from which to allocate the IPv6 CIDR block.", "VpcId": "The ID of the VPC." } @@ -15137,7 +15139,7 @@ "DestinationDetails": "Configuration details of either a CloudWatch Logs destination or Kinesis Data Firehose destination.", "DestinationType": "Specify either CloudWatch Logs or Kinesis Data Firehose as the destination type. Valid values are either `cloudwatch-logs` or `kinesis-firehose` .", "LogFormat": "Valid values are either `json` or `text` .", - "LogType": "Valid value is `slow-log` . Refers to [slow-log](https://docs.aws.amazon.com/https://redis.io/commands/slowlog) ." + "LogType": "Valid value is either `slow-log` , which refers to [slow-log](https://docs.aws.amazon.com/https://redis.io/commands/slowlog) or `engine-log` ." } }, "AWS::ElastiCache::GlobalReplicationGroup": { @@ -15246,7 +15248,7 @@ "SnapshotWindow": "The daily time range (in UTC) during which ElastiCache begins taking a daily snapshot of your node group (shard).\n\nExample: `05:00-09:00`\n\nIf you do not specify this parameter, ElastiCache automatically chooses an appropriate time range.", "SnapshottingClusterId": "The cluster ID that is used as the daily snapshot source for the replication group. This parameter cannot be set for Redis (cluster mode enabled) replication groups.", "Tags": "A list of tags to be added to this resource. Tags are comma-separated key,value pairs (e.g. Key= `myKey` , Value= `myKeyValue` . You can include multiple tags as shown following: Key= `myKey` , Value= `myKeyValue` Key= `mySecondKey` , Value= `mySecondKeyValue` . Tags on replication groups will be replicated to all nodes.", - "TransitEncryptionEnabled": "A flag that enables in-transit encryption when set to `true` .\n\nYou cannot modify the value of `TransitEncryptionEnabled` after the cluster is created. To enable in-transit encryption on a cluster you must set `TransitEncryptionEnabled` to `true` when you create a cluster.\n\nThis parameter is valid only if the `Engine` parameter is `redis` , the `EngineVersion` parameter is `3.2.6` or `4.x` or `5.x` , and the cluster is being created in an Amazon VPC.\n\nIf you enable in-transit encryption, you must also specify a value for `CacheSubnetGroup` .\n\n*Required:* Only available when creating a replication group in an Amazon VPC using redis version `3.2.6` or `4.x` onward.\n\nDefault: `false`\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` .", + "TransitEncryptionEnabled": "A flag that enables in-transit encryption when set to `true` .\n\nYou cannot modify the value of `TransitEncryptionEnabled` after the cluster is created. To enable in-transit encryption on a cluster you must set `TransitEncryptionEnabled` to `true` when you create a cluster.\n\nThis parameter is valid only if the `Engine` parameter is `redis` , the `EngineVersion` parameter is `3.2.6` or `4.x` onward, and the cluster is being created in an Amazon VPC.\n\nIf you enable in-transit encryption, you must also specify a value for `CacheSubnetGroup` .\n\n*Required:* Only available when creating a replication group in an Amazon VPC using redis version `3.2.6` or `4.x` onward.\n\nDefault: `false`\n\n> For HIPAA compliance, you must specify `TransitEncryptionEnabled` as `true` , an `AuthToken` , and a `CacheSubnetGroup` .", "UserGroupIds": "The list of user groups to associate with the replication group." } }, @@ -15261,7 +15263,7 @@ "attributes": {}, "description": "Configuration details of either a CloudWatch Logs destination or Kinesis Data Firehose destination.", "properties": { - "CloudWatchLogsDetails": "", + "CloudWatchLogsDetails": "The configuration details of the CloudWatch Logs destination. Note that this field is marked as required but only if CloudWatch Logs was chosen as the destination.", "KinesisFirehoseDetails": "The configuration details of the Kinesis Data Firehose destination. Note that this field is marked as required but only if Kinesis Data Firehose was chosen as the destination." } }, @@ -15279,7 +15281,7 @@ "DestinationDetails": "Configuration details of either a CloudWatch Logs destination or Kinesis Data Firehose destination.", "DestinationType": "Specify either CloudWatch Logs or Kinesis Data Firehose as the destination type. Valid values are either `cloudwatch-logs` or `kinesis-firehose` .", "LogFormat": "Valid values are either `json` or `text` .", - "LogType": "Valid value is `slow-log` . Refers to [slow-log](https://docs.aws.amazon.com/https://redis.io/commands/slowlog) ." + "LogType": "Valid value is either `slow-log` , which refers to [slow-log](https://docs.aws.amazon.com/https://redis.io/commands/slowlog) or `engine-log` ." } }, "AWS::ElastiCache::ReplicationGroup.NodeGroupConfiguration": { @@ -24545,7 +24547,7 @@ "FilterCriteria": "(Streams and Amazon SQS) 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* - `MyFunction` .\n- *Function ARN* - `arn:aws:lambda:us-west-2:123456789012:function:MyFunction` .\n- *Version or Alias ARN* - `arn:aws:lambda:us-west-2:123456789012:function:MyFunction:PROD` .\n- *Partial ARN* - `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`", - "MaximumBatchingWindowInSeconds": "(Streams and Amazon SQS standard queues) The maximum amount of time, in seconds, that Lambda spends gathering records before invoking the function.\n\nDefault: 0\n\nRelated setting: When you set `BatchSize` to a value greater than 10, you must set `MaximumBatchingWindowInSeconds` to at least 1.", + "MaximumBatchingWindowInSeconds": "(Streams and Amazon SQS standard queues) The maximum amount of time, in seconds, that Lambda spends gathering records before invoking the function.\n\nDefault: 0", "MaximumRecordAgeInSeconds": "(Streams only) Discard records older than the specified age. The default value is -1,\nwhich sets the maximum age to infinite. When the value is set to infinite, Lambda never discards old records.", "MaximumRetryAttempts": "(Streams only) Discard records after the specified number of retries. The default value is -1,\nwhich sets the maximum number of retries to infinite. When MaximumRetryAttempts is infinite, Lambda retries failed records until the record expires in the event source.", "ParallelizationFactor": "(Streams only) The number of batches to process concurrently from each shard. The default value is 1.", @@ -26080,7 +26082,7 @@ "attributes": { "Ref": "`Ref` returns the Amazon MSK cluster ARN. For example:\n\n`REF MyTestCluster`\n\nFor the Amazon MSK cluster `MyTestCluster` , Ref returns the ARN of the cluster." }, - "description": "The `AWS::MSK::Cluster` resource creates an Amazon MSK cluster. For more information, see [What Is Amazon MSK?](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) in the *Amazon MSK Developer Guide* .", + "description": "The `AWS::MSK::Cluster` resource creates an Amazon MSK cluster . For more information, see [What Is Amazon MSK?](https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html) in the *Amazon MSK Developer Guide* .", "properties": { "BrokerNodeGroupInfo": "The setup to be used for brokers in the cluster.", "ClientAuthentication": "Includes information related to client authentication.", @@ -26088,8 +26090,8 @@ "ConfigurationInfo": "The Amazon MSK configuration to use for the cluster.", "EncryptionInfo": "Includes all encryption-related information.", "EnhancedMonitoring": "Specifies the level of monitoring for the MSK cluster. The possible values are `DEFAULT` , `PER_BROKER` , and `PER_TOPIC_PER_BROKER` .", - "KafkaVersion": "The version of Apache Kafka. You can use Amazon MSK to create clusters that use Apache Kafka versions 1.1.1 and 2.2.1.", - "LoggingInfo": "You can configure your MSK cluster to send broker logs to different destination types. This is a container for the configuration details related to broker logs.", + "KafkaVersion": "The version of Apache Kafka. For more information, see [Supported Apache Kafka versions](https://docs.aws.amazon.com/msk/latest/developerguide/supported-kafka-versions.html) in the Amazon MSK Developer Guide.", + "LoggingInfo": "You can configure your Amazon MSK cluster to send broker logs to different destination types. This is a container for the configuration details related to broker logs.", "NumberOfBrokerNodes": "The number of broker nodes you want in the Amazon MSK cluster. You can submit an update to increase the number of broker nodes in a cluster.", "OpenMonitoring": "The settings for open monitoring.", "Tags": "A map of key:value pairs to apply to this resource. Both key and value are of type String." @@ -26097,11 +26099,11 @@ }, "AWS::MSK::Cluster.BrokerLogs": { "attributes": {}, - "description": "You can configure your MSK cluster to send broker logs to different destination types. This configuration specifies the details of these destinations.", + "description": "You can configure your Amazon MSK cluster to send broker logs to different destination types. This configuration specifies the details of these destinations.", "properties": { "CloudWatchLogs": "Details of the CloudWatch Logs destination for broker logs.", "Firehose": "Details of the Kinesis Data Firehose delivery stream that is the destination for broker logs.", - "S3": "Details of the Amazon S3 destination for broker logs." + "S3": "Details of the Amazon MSK destination for broker logs." } }, "AWS::MSK::Cluster.BrokerNodeGroupInfo": { @@ -26130,7 +26132,7 @@ "description": "Details of the CloudWatch Logs destination for broker logs.", "properties": { "Enabled": "Specifies whether broker logs get sent to the specified CloudWatch Logs destination.", - "LogGroup": "The CloudWatch log group that is the destination for broker logs." + "LogGroup": "The CloudWatch Logs group that is the destination for broker logs." } }, "AWS::MSK::Cluster.ConfigurationInfo": { @@ -26166,8 +26168,8 @@ "attributes": {}, "description": "The settings for encrypting data in transit.", "properties": { - "ClientBroker": "Indicates the encryption setting for data in transit between clients and brokers. The following are the possible values.\n\n- `TLS` means that client-broker communication is enabled with TLS only.\n- `TLS_PLAINTEXT` means that client-broker communication is enabled for both TLS-encrypted, as well as plaintext data.\n- `PLAINTEXT` means that client-broker communication is enabled in plaintext only.\n\nThe default value is `TLS` .", - "InCluster": "When set to true, it indicates that data communication among the broker nodes of the cluster is encrypted. When set to false, the communication happens in plaintext. The default value is true." + "ClientBroker": "Indicates the encryption setting for data in transit between clients and brokers. The following are the possible values.\n\n- `TLS` means that client-broker communication is enabled with TLS only.\n- `TLS_PLAINTEXT` means that client-broker communication is enabled for both TLS-encrypted, as well as plain text data.\n- `PLAINTEXT` means that client-broker communication is enabled in plain text only.\n\nThe default value is `TLS` .", + "InCluster": "When set to true, it indicates that data communication among the broker nodes of the cluster is encrypted. When set to false, the communication happens in plain text. The default value is true." } }, "AWS::MSK::Cluster.EncryptionInfo": { @@ -26202,9 +26204,9 @@ }, "AWS::MSK::Cluster.LoggingInfo": { "attributes": {}, - "description": "You can configure your MSK cluster to send broker logs to different destination types. This is a container for the configuration details related to broker logs.", + "description": "You can configure your Amazon MSK cluster to send broker logs to different destination types. This is a container for the configuration details related to broker logs.", "properties": { - "BrokerLogs": "You can configure your MSK cluster to send broker logs to different destination types. This configuration specifies the details of these destinations." + "BrokerLogs": "You can configure your Amazon MSK cluster to send broker logs to different destination types. This configuration specifies the details of these destinations." } }, "AWS::MSK::Cluster.NodeExporter": { @@ -26233,7 +26235,7 @@ "attributes": {}, "description": "Specifies whether the cluster's brokers are accessible from the internet. Public access is off by default.", "properties": { - "Type": "Set to DISABLED to turn off public access or to SERVICE_PROVIDED_EIPS to turn it on. Public access if off by default." + "Type": "Set to `DISABLED` to turn off public access or to `SERVICE_PROVIDED_EIPS` to turn it on. Public access if off by default." } }, "AWS::MSK::Cluster.S3": { @@ -29630,13 +29632,13 @@ }, "AWS::OpenSearchService::Domain": { "attributes": { - "Arn": "The Amazon Resource Name (ARN) of the domain, such as `arn:aws:es:us-west-2:123456789012:domain/mystack-1ab2cdefghij` . This returned value is the same as the one returned by `AWS::OpenSearchService::Domain.Arn` .", + "Arn": "The Amazon Resource Name (ARN) of the domain, such as `arn:aws:es:us-west-2:123456789012:domain/mystack-1ab2cdefghij` .", "DomainArn": "", "DomainEndpoint": "The domain-specific endpoint used for requests to the OpenSearch APIs, such as `search-mystack-1ab2cdefghij-ab1c2deckoyb3hofw7wpqa3cm.us-west-1.es.amazonaws.com` .", - "Id": "", + "Id": "The resource ID. For example, `123456789012/my-domain` .", "Ref": "When the logical ID of this resource is provided to the Ref intrinsic function, Ref returns the resource name, such as `mystack-abc1d2efg3h4.` For more information about using the Ref function, see [Ref](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html) ." }, - "description": "The AWS::OpenSearchService::Domain resource creates an Amazon OpenSearch Service (successor to Amazon Elasticsearch Service) domain.\n\n> The `AWS::OpenSearchService::Domain` resource replaces the legacy [AWS::Elasticsearch::Domain](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html) resource. While the Elasticsearch resource and options are still supported, we recommend modifying your existing Cloudformation templates to use the new OpenSearch Service resource, which supports both OpenSearch and legacy Elasticsearch engines. For instructions to upgrade domains defined within CloudFormation from Elasticsearch to OpenSearch, see [Remarks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html#aws-resource-elasticsearch-domain--remarks) .", + "description": "The AWS::OpenSearchService::Domain resource creates an Amazon OpenSearch Service (successor to Amazon Elasticsearch Service) domain.\n\n> The `AWS::OpenSearchService::Domain` resource replaces the legacy [AWS::Elasticsearch::Domain](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html) resource. While the Elasticsearch resource and options are still supported, we recommend modifying your existing Cloudformation templates to use the new OpenSearch Service resource, which supports both OpenSearch and legacy Elasticsearch engines. For instructions to upgrade domains defined within CloudFormation from Elasticsearch to OpenSearch, see [Remarks](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-opensearchservice-domain.html#aws-resource-opensearchservice-domain--remarks) .", "properties": { "AccessPolicies": "An AWS Identity and Access Management ( IAM ) policy document that specifies who can access the OpenSearch Service domain and their permissions. For more information, see [Configuring access policies](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ac.html#ac-creating) in the *Amazon OpenSearch Service Developer Guide* .", "AdvancedOptions": "Additional options to specify for the OpenSearch Service domain. For more information, see [Advanced cluster parameters](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/createupdatedomains.html#createdomain-configure-advanced-options) in the *Amazon OpenSearch Service Developer Guide* .", @@ -32156,7 +32158,7 @@ "AllowMajorVersionUpgrade": "A value that indicates whether major version upgrades are allowed. Changing this parameter doesn't result in an outage and the change is asynchronously applied as soon as possible.\n\nConstraints: Major version upgrades must be allowed when specifying a value for the `EngineVersion` parameter that is a different major version than the DB instance's current version.", "AssociatedRoles": "The AWS Identity and Access Management (IAM) roles associated with the DB instance.", "AutoMinorVersionUpgrade": "A value that indicates whether minor engine upgrades are applied automatically to the DB instance during the maintenance window. By default, minor engine upgrades are applied automatically.", - "AvailabilityZone": "The Availability Zone that the database instance will be created in.\n\nDefault: A random, system-chosen Availability Zone in the endpoint's region.\n\nExample: `us-east-1d`\n\nConstraint: The AvailabilityZone parameter cannot be specified if the MultiAZ parameter is set to `true` . The specified Availability Zone must be in the same region as the current endpoint.", + "AvailabilityZone": "The Availability Zone (AZ) where the database will be created. For information on AWS Regions and Availability Zones, see [Regions and Availability Zones](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html) .\n\n*Amazon Aurora*\n\nNot applicable. Availability Zones are managed by the DB cluster.\n\nDefault: A random, system-chosen Availability Zone in the endpoint's AWS Region.\n\nExample: `us-east-1d`\n\nConstraint: The `AvailabilityZone` parameter can't be specified if the DB instance is a Multi-AZ deployment. The specified Availability Zone must be in the same AWS Region as the current endpoint.\n\n> If you're creating a DB instance in an RDS on VMware environment, specify the identifier of the custom Availability Zone to create the DB instance in.\n> \n> For more information about RDS on VMware, see the [RDS on VMware User Guide.](https://docs.aws.amazon.com/AmazonRDS/latest/RDSonVMwareUserGuide/rds-on-vmware.html)", "BackupRetentionPeriod": "The number of days for which automated backups are retained. Setting this parameter to a positive number enables backups. Setting this parameter to 0 disables automated backups.\n\n*Amazon Aurora*\n\nNot applicable. The retention period for automated backups is managed by the DB cluster.\n\nDefault: 1\n\nConstraints:\n\n- Must be a value from 0 to 35\n- Can't be set to 0 if the DB instance is a source to read replicas", "CACertificateIdentifier": "The identifier of the CA certificate for this DB instance.\n\n> Specifying or updating this property triggers a reboot. \n\nFor more information about CA certificate identifiers for RDS DB engines, see [Rotating Your SSL/TLS Certificate](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL-certificate-rotation.html) in the *Amazon RDS User Guide* .\n\nFor more information about CA certificate identifiers for Aurora DB engines, see [Rotating Your SSL/TLS Certificate](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL-certificate-rotation.html) in the *Amazon Aurora User Guide* .", "CharacterSetName": "For supported engines, indicates that the DB instance should be associated with the specified character set.\n\n*Amazon Aurora*\n\nNot applicable. The character set is managed by the DB cluster. For more information, see [AWS::RDS::DBCluster](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html) .", @@ -32228,7 +32230,7 @@ }, "description": "The `AWS::RDS::DBParameterGroup` resource creates a custom parameter group for an RDS database family.\n\nThis type can be declared in a template and referenced in the `DBParameterGroupName` property of an `[AWS::RDS::DBInstance](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html)` resource.\n\nFor information about configuring parameters for Amazon RDS DB instances, see [Working with DB parameter groups](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html) in the *Amazon RDS User Guide* .\n\nFor information about configuring parameters for Amazon Aurora DB instances, see [Working with DB parameter groups and DB cluster parameter groups](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithParamGroups.html) in the *Amazon Aurora User Guide* .\n\n> Applying a parameter group to a DB instance may require the DB instance to reboot, resulting in a database outage for the duration of the reboot.", "properties": { - "Description": "Provides the customer-specified description for this DB Parameter Group.", + "Description": "Provides the customer-specified description for this DB parameter group.", "Family": "The DB parameter group family name. A DB parameter group can be associated with one and only one DB parameter group family, and can be applied only to a DB instance running a DB engine and engine version compatible with that DB parameter group family.\n\n> The DB parameter group family can't be changed when updating a DB 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 `[CreateDBParameterGroup](https://docs.aws.amazon.com//AmazonRDS/latest/APIReference/API_CreateDBParameterGroup.html)` .", "Parameters": "An array of parameter names and values for the parameter update. At least one parameter name and value must be supplied. Subsequent arguments are optional.\n\nFor more information about DB parameters and DB parameter groups for Amazon RDS DB engines, see [Working with DB Parameter Groups](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html) in the *Amazon RDS User Guide* .\n\nFor more information about DB cluster and DB instance parameters and parameter groups for Amazon Aurora DB engines, see [Working with DB Parameter Groups and DB Cluster Parameter Groups](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithParamGroups.html) in the *Amazon Aurora User Guide* .\n\n> AWS CloudFormation doesn't support specifying an apply method for each individual parameter. The default apply method for each parameter is used.", "Tags": "Tags to assign to the DB parameter group." @@ -32332,7 +32334,7 @@ "properties": { "DBSecurityGroupIngress": "Ingress rules to be applied to the DB security group.", "EC2VpcId": "The identifier of an Amazon VPC. This property indicates the VPC that this DB security group belongs to.\n\n> The `EC2VpcId` property is for backward compatibility with older regions, and is no longer recommended for providing security information to an RDS DB instance.", - "GroupDescription": "Provides the description of the DB Security Group.", + "GroupDescription": "Provides the description of the DB security group.", "Tags": "Tags to assign to the DB security group." } }, @@ -32341,9 +32343,9 @@ "description": "The `Ingress` property type specifies an individual ingress rule within an `AWS::RDS::DBSecurityGroup` resource.", "properties": { "CIDRIP": "The IP range to authorize.", - "EC2SecurityGroupId": "Id of the EC2 Security Group to authorize. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", - "EC2SecurityGroupName": "Name of the EC2 Security Group to authorize. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", - "EC2SecurityGroupOwnerId": "AWS Account Number of the owner of the EC2 Security Group specified in the EC2SecurityGroupName parameter. The AWS Access Key ID is not an acceptable value. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided." + "EC2SecurityGroupId": "Id of the EC2 security group to authorize. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", + "EC2SecurityGroupName": "Name of the EC2 security group to authorize. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", + "EC2SecurityGroupOwnerId": "AWS account number of the owner of the EC2 security group specified in the `EC2SecurityGroupName` parameter. The AWS access key ID isn't an acceptable value. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided." } }, "AWS::RDS::DBSecurityGroupIngress": { @@ -32353,10 +32355,10 @@ "description": "The `AWS::RDS::DBSecurityGroupIngress` resource enables ingress to a DB security group using one of two forms of authorization. First, you can add EC2 or VPC security groups to the DB security group if the application using the database is running on EC2 or VPC instances. Second, IP ranges are available if the application accessing your database is running on the Internet.\n\nThis type supports updates. For more information about updating stacks, see [AWS CloudFormation Stacks Updates](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks.html) .\n\nFor details about the settings for DB security group ingress, see [AuthorizeDBSecurityGroupIngress](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AuthorizeDBSecurityGroupIngress.html) .", "properties": { "CIDRIP": "The IP range to authorize.", - "DBSecurityGroupName": "The name of the DB Security Group to add authorization to.", - "EC2SecurityGroupId": "Id of the EC2 Security Group to authorize. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", - "EC2SecurityGroupName": "Name of the EC2 Security Group to authorize. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", - "EC2SecurityGroupOwnerId": "AWS Account Number of the owner of the EC2 Security Group specified in the EC2SecurityGroupName parameter. The AWS Access Key ID is not an acceptable value. For VPC DB Security Groups, `EC2SecurityGroupId` must be provided. Otherwise, EC2SecurityGroupOwnerId and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided." + "DBSecurityGroupName": "The name of the DB security group to add authorization to.", + "EC2SecurityGroupId": "Id of the EC2 security group to authorize. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", + "EC2SecurityGroupName": "Name of the EC2 security group to authorize. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided.", + "EC2SecurityGroupOwnerId": "AWS account number of the owner of the EC2 security group specified in the `EC2SecurityGroupName` parameter. The AWS access key ID isn't an acceptable value. For VPC DB security groups, `EC2SecurityGroupId` must be provided. Otherwise, `EC2SecurityGroupOwnerId` and either `EC2SecurityGroupName` or `EC2SecurityGroupId` must be provided." } }, "AWS::RDS::DBSubnetGroup": { @@ -32365,9 +32367,9 @@ }, "description": "The `AWS::RDS::DBSubnetGroup` resource creates a database subnet group. Subnet groups must contain at least two subnets in two different Availability Zones in the same region.\n\nFor more information, see [Working with DB subnet groups](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_VPC.WorkingWithRDSInstanceinaVPC.html#USER_VPC.Subnets) in the *Amazon RDS User Guide* .", "properties": { - "DBSubnetGroupDescription": "The description for the DB Subnet Group.", + "DBSubnetGroupDescription": "The description for the DB subnet group.", "DBSubnetGroupName": "The name for the DB subnet group. This value is stored as a lowercase string.\n\nConstraints: Must contain no more than 255 lowercase alphanumeric characters or hyphens. Must not be \"Default\".\n\nExample: `mysubnetgroup`", - "SubnetIds": "The EC2 Subnet IDs for the DB Subnet Group.", + "SubnetIds": "The EC2 Subnet IDs for the DB subnet group.", "Tags": "Tags to assign to the DB subnet group." } }, @@ -32377,8 +32379,8 @@ }, "description": "The `AWS::RDS::EventSubscription` resource allows you to receive notifications for Amazon Relational Database Service events through the Amazon Simple Notification Service (Amazon SNS). For more information, see [Using Amazon RDS Event Notification](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html) in the *Amazon RDS User Guide* .", "properties": { - "Enabled": "A Boolean value; set to *true* to activate the subscription, set to *false* to create the subscription but not active it.", - "EventCategories": "A list of event categories for a SourceType that you want to subscribe to. You can see a list of the categories for a given SourceType in the [Events](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.html) topic in the Amazon RDS User Guide or by using the *DescribeEventCategories* action.", + "Enabled": "A value that indicates whether to activate the subscription. If the event notification subscription isn't activated, the subscription is created but not active.", + "EventCategories": "A list of event categories for a particular source type ( `SourceType` ) that you want to subscribe to. You can see a list of the categories for a given source type in the \"Amazon RDS event categories and event messages\" section of the [*Amazon RDS User Guide*](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.Messages.html) or the [*Amazon Aurora User Guide*](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_Events.Messages.html) . You can also see this list by using the `DescribeEventCategories` operation.", "SnsTopicArn": "The Amazon Resource Name (ARN) of the SNS topic created for event notification. The ARN is created by Amazon SNS when you create a topic and subscribe to it.", "SourceIds": "The list of identifiers of the event sources for which events are returned. If not specified, then all sources are included in the response. An identifier must begin with a letter and must contain only ASCII letters, digits, and hyphens. It can't end with a hyphen or contain two consecutive hyphens.\n\nConstraints:\n\n- If a `SourceIds` value is supplied, `SourceType` must also be provided.\n- If the source type is a DB instance, a `DBInstanceIdentifier` value must be supplied.\n- If the source type is a DB cluster, a `DBClusterIdentifier` value must be supplied.\n- If the source type is a DB parameter group, a `DBParameterGroupName` value must be supplied.\n- If the source type is a DB security group, a `DBSecurityGroupName` value must be supplied.\n- If the source type is a DB snapshot, a `DBSnapshotIdentifier` value must be supplied.\n- If the source type is a DB cluster snapshot, a `DBClusterSnapshotIdentifier` value must be supplied.", "SourceType": "The type of source that is generating the events. For example, if you want to be notified of events generated by a DB instance, set this parameter to `db-instance` . If this value isn't specified, all events are returned.\n\nValid values: `db-instance` | `db-cluster` | `db-parameter-group` | `db-security-group` | `db-snapshot` | `db-cluster-snapshot`" @@ -34072,24 +34074,24 @@ }, "AWS::S3::Bucket.Rule": { "attributes": {}, - "description": "Specifies lifecycle rules for an Amazon S3 bucket. For more information, see [Put Bucket Lifecycle Configuration](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html) in the *Amazon S3 API Reference* .", + "description": "Specifies lifecycle rules for an Amazon S3 bucket. For more information, see [Put Bucket Lifecycle Configuration](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html) in the *Amazon S3 API Reference* .\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", "properties": { - "AbortIncompleteMultipartUpload": "Specifies a lifecycle rule that stops incomplete multipart uploads to an Amazon S3 bucket.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", - "ExpirationDate": "Indicates when objects are deleted from Amazon S3 and Amazon S3 Glacier. The date value must be in ISO 8601 format. The time is always midnight UTC. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", - "ExpirationInDays": "Indicates the number of days after creation when objects are deleted from Amazon S3 and Amazon S3 Glacier. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", + "AbortIncompleteMultipartUpload": "Specifies a lifecycle rule that stops incomplete multipart uploads to an Amazon S3 bucket.", + "ExpirationDate": "Indicates when objects are deleted from Amazon S3 and Amazon S3 Glacier. The date value must be in ISO 8601 format. The time is always midnight UTC. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time.", + "ExpirationInDays": "Indicates the number of days after creation when objects are deleted from Amazon S3 and Amazon S3 Glacier. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time.", "ExpiredObjectDeleteMarker": "Indicates whether Amazon S3 will remove a delete marker without any noncurrent versions. If set to true, the delete marker will be removed if there are no noncurrent versions. This cannot be specified with `ExpirationInDays` , `ExpirationDate` , or `TagFilters` .", "Id": "Unique identifier for the rule. The value can't be longer than 255 characters.", "NoncurrentVersionExpiration": "Specifies when noncurrent object versions expire. Upon expiration, Amazon S3 permanently deletes the noncurrent object versions. You set this lifecycle configuration action on a bucket that has versioning enabled (or suspended) to request that Amazon S3 delete noncurrent object versions at a specific period in the object's lifetime.", - "NoncurrentVersionExpirationInDays": "(Deprecated.) For buckets with versioning enabled (or suspended), specifies the time, in days, between when a new version of the object is uploaded to the bucket and when old versions of the object expire. When object versions expire, Amazon S3 permanently deletes them. If you specify a transition and expiration time, the expiration time must be later than the transition time.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", - "NoncurrentVersionTransition": "(Deprecated.) For buckets with versioning enabled (or suspended), specifies when non-current objects transition to a specified storage class. If you specify a transition and expiration time, the expiration time must be later than the transition time. If you specify this property, don't specify the `NoncurrentVersionTransitions` property.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", - "NoncurrentVersionTransitions": "For buckets with versioning enabled (or suspended), one or more transition rules that specify when non-current objects transition to a specified storage class. If you specify a transition and expiration time, the expiration time must be later than the transition time. If you specify this property, don't specify the `NoncurrentVersionTransition` property.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", + "NoncurrentVersionExpirationInDays": "(Deprecated.) For buckets with versioning enabled (or suspended), specifies the time, in days, between when a new version of the object is uploaded to the bucket and when old versions of the object expire. When object versions expire, Amazon S3 permanently deletes them. If you specify a transition and expiration time, the expiration time must be later than the transition time.", + "NoncurrentVersionTransition": "(Deprecated.) For buckets with versioning enabled (or suspended), specifies when non-current objects transition to a specified storage class. If you specify a transition and expiration time, the expiration time must be later than the transition time. If you specify this property, don't specify the `NoncurrentVersionTransitions` property.", + "NoncurrentVersionTransitions": "For buckets with versioning enabled (or suspended), one or more transition rules that specify when non-current objects transition to a specified storage class. If you specify a transition and expiration time, the expiration time must be later than the transition time. If you specify this property, don't specify the `NoncurrentVersionTransition` property.", "ObjectSizeGreaterThan": "Specifies the minimum object size in bytes for this rule to apply to. For more information about size based rules, see [Lifecycle configuration using size-based rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-configuration-examples.html#lc-size-rules) in the *Amazon S3 User Guide* .", "ObjectSizeLessThan": "Specifies the maximum object size in bytes for this rule to apply to. For more information about sized based rules, see [Lifecycle configuration using size-based rules](https://docs.aws.amazon.com/AmazonS3/latest/userguide/lifecycle-configuration-examples.html#lc-size-rules) in the *Amazon S3 User Guide* .", "Prefix": "Object key prefix that identifies one or more objects to which this rule applies.\n\n> Replacement must be made for object keys containing special characters (such as carriage returns) when using XML requests. For more information, see [XML related object key constraints](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html#object-key-xml-related-constraints) .", "Status": "If `Enabled` , the rule is currently being applied. If `Disabled` , the rule is not currently being applied.", "TagFilters": "Tags to use to identify a subset of objects to which the lifecycle rule applies.", - "Transition": "(Deprecated.) Specifies when an object transitions to a specified storage class. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time. If you specify this property, don't specify the `Transitions` property.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` .", - "Transitions": "One or more transition rules that specify when an object transitions to a specified storage class. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time. If you specify this property, don't specify the `Transition` property.\n\nYou must specify at least one of the following properties: `AbortIncompleteMultipartUpload` , `ExpirationDate` , `ExpirationInDays` , `NoncurrentVersionExpirationInDays` , `NoncurrentVersionTransition` , `NoncurrentVersionTransitions` , `Transition` , or `Transitions` ." + "Transition": "(Deprecated.) Specifies when an object transitions to a specified storage class. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time. If you specify this property, don't specify the `Transitions` property.", + "Transitions": "One or more transition rules that specify when an object transitions to a specified storage class. If you specify an expiration and transition time, you must use the same time unit for both properties (either in days or by date). The expiration time must also be later than the transition time. If you specify this property, don't specify the `Transition` property." } }, "AWS::S3::Bucket.S3KeyFilter": { @@ -34804,7 +34806,7 @@ }, "AWS::SSM::Association": { "attributes": { - "AssociationId": "" + "AssociationId": "The association ID." }, "description": "The `AWS::SSM::Association` resource creates a State Manager association for your managed instances. A State Manager association defines the state that you want to maintain on your instances. For example, an association can specify that anti-virus software must be installed and running on your instances, or that certain ports must be closed. For static targets, the association specifies a schedule for when the configuration is reapplied. For dynamic targets, such as an AWS Resource Groups or an AWS Auto Scaling Group, State Manager applies the configuration when new instances are added to the group. The association also specifies actions to take when applying the configuration. For example, an association for anti-virus software might run once a day. If the software is not installed, then State Manager installs it. If the software is installed, but the service is not running, then the association might instruct State Manager to start the service.", "properties": { @@ -35113,7 +35115,7 @@ "AWS::SSM::ResourceDataSync": { "attributes": { "Ref": "`Ref` returns the name of the resource data sync, such as `TestResourceDataSync` .", - "SyncName": "" + "SyncName": "The name of the resource data sync." }, "description": "The `AWS::SSM::ResourceDataSync` resource creates, updates, or deletes a resource data sync for AWS Systems Manager . A resource data sync helps you view data from multiple sources in a single location. Systems Manager offers two types of resource data sync: `SyncToDestination` and `SyncFromSource` .\n\nYou can configure Systems Manager Inventory to use the `SyncToDestination` type to synchronize Inventory data from multiple AWS Regions to a single Amazon S3 bucket.\n\nYou can configure Systems Manager Explorer to use the `SyncFromSource` type to synchronize operational work items (OpsItems) and operational data (OpsData) from multiple AWS Regions . This type can synchronize OpsItems and OpsData from multiple AWS accounts and Regions or from an `EntireOrganization` by using AWS Organizations .\n\nA resource data sync is an asynchronous operation that returns immediately. After a successful initial sync is completed, the system continuously syncs data.\n\nBy default, data is not encrypted in Amazon S3 . We strongly recommend that you enable encryption in Amazon S3 to ensure secure data storage. We also recommend that you secure access to the Amazon S3 bucket by creating a restrictive bucket policy.\n\nFor more information, see [Configuring Inventory Collection](https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-inventory-configuring.html#sysman-inventory-datasync) and [Setting Up Systems Manager Explorer to Display Data from Multiple Accounts and Regions](https://docs.aws.amazon.com/systems-manager/latest/userguide/Explorer-resource-data-sync.html) in the *AWS Systems Manager User Guide* .\n\nImportant: The following *Syntax* section shows all fields that are supported for a resource data sync. The *Examples* section below shows the recommended way to specify configurations for each sync type. Please see the *Examples* section when you create your resource data sync.", "properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json index b04c9b991d117..622c282c40348 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ACMPCA.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ACMPCA::Certificate.ApiPassthrough": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-acmpca-certificate-apipassthrough.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json index 066fa41a16091..a5814fff40048 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_APS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::APS::RuleGroupsNamespace": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json index 1c52130ca7172..1d3ae77b4f266 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AccessAnalyzer.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AccessAnalyzer::Analyzer.ArchiveRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-accessanalyzer-analyzer-archiverule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json index e410da44a289c..fa5275d5cd707 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmazonMQ.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AmazonMQ::Broker.ConfigurationId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amazonmq-broker-configurationid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json index 6cba09d4006af..1b9e895909597 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Amplify.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Amplify::App.AutoBranchCreationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplify-app-autobranchcreationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json index e3459e1eab77b..977b1c8006948 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AmplifyUIBuilder.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AmplifyUIBuilder::Component.ComponentBindingPropertiesValue": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-amplifyuibuilder-component-componentbindingpropertiesvalue.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json index f9d78d21cc5ed..c1bce1262a552 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGateway.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ApiGateway::ApiKey.StageKey": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigateway-apikey-stagekey.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json index 755ff079c3395..630ad7c2d2331 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApiGatewayV2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ApiGatewayV2::Api.BodyS3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apigatewayv2-api-bodys3location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json index c1e2d83e71676..6a7f6be1a2508 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppConfig.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppConfig::Application.Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appconfig-application-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json index 470bc338af602..aa01f96a4f378 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppFlow.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppFlow::ConnectorProfile.AmplitudeConnectorProfileCredentials": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appflow-connectorprofile-amplitudeconnectorprofilecredentials.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json index 12a5f564eb043..2fb1e24a92662 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppIntegrations.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppIntegrations::EventIntegration.EventFilter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appintegrations-eventintegration-eventfilter.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json index 213aea908c107..123b1581c8a8d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppMesh.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppMesh::GatewayRoute.GatewayRouteHostnameMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-gatewayroute-gatewayroutehostnamematch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json index b1ff46dfc03fc..09037684f7a76 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppRunner.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppRunner::Service.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-service-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json index 65267bb407da0..17545674f1490 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppStream.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppStream::AppBlock.S3Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-appblock-s3location.html", @@ -81,6 +81,23 @@ } } }, + "AWS::AppStream::Entitlement.Attribute": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-entitlement-attribute.html", + "Properties": { + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-entitlement-attribute.html#cfn-appstream-entitlement-attribute-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-entitlement-attribute.html#cfn-appstream-entitlement-attribute-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::AppStream::Fleet.ComputeCapacity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appstream-fleet-computecapacity.html", "Properties": { @@ -402,6 +419,29 @@ } } }, + "AWS::AppStream::ApplicationEntitlementAssociation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-applicationentitlementassociation.html", + "Properties": { + "ApplicationIdentifier": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-applicationentitlementassociation.html#cfn-appstream-applicationentitlementassociation-applicationidentifier", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "EntitlementName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-applicationentitlementassociation.html#cfn-appstream-applicationentitlementassociation-entitlementname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "StackName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-applicationentitlementassociation.html#cfn-appstream-applicationentitlementassociation-stackname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::AppStream::ApplicationFleetAssociation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-applicationfleetassociation.html", "Properties": { @@ -443,6 +483,51 @@ } } }, + "AWS::AppStream::Entitlement": { + "Attributes": { + "CreatedTime": { + "PrimitiveType": "String" + }, + "LastModifiedTime": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html", + "Properties": { + "AppVisibility": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html#cfn-appstream-entitlement-appvisibility", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Attributes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html#cfn-appstream-entitlement-attributes", + "DuplicatesAllowed": false, + "ItemType": "Attribute", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html#cfn-appstream-entitlement-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html#cfn-appstream-entitlement-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "StackName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-entitlement.html#cfn-appstream-entitlement-stackname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::AppStream::Fleet": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appstream-fleet.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json index 69766ae997e64..d52e008624e8c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AppSync.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AppSync::DataSource.AuthorizationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-authorizationconfig.html", @@ -424,7 +424,7 @@ "Ttl": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-resolver-cachingconfig.html#cfn-appsync-resolver-cachingconfig-ttl", "PrimitiveType": "Double", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -731,6 +731,12 @@ "Required": true, "UpdateType": "Mutable" }, + "MaxBatchSize": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-functionconfiguration.html#cfn-appsync-functionconfiguration-maxbatchsize", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-functionconfiguration.html#cfn-appsync-functionconfiguration-name", "PrimitiveType": "String", @@ -906,6 +912,12 @@ "Required": false, "UpdateType": "Mutable" }, + "MaxBatchSize": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-resolver.html#cfn-appsync-resolver-maxbatchsize", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "PipelineConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-resolver.html#cfn-appsync-resolver-pipelineconfig", "Required": false, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json index d7446ebdd23a1..d9755e4891b40 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationAutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ApplicationAutoScaling::ScalableTarget.ScalableTargetAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationautoscaling-scalabletarget-scalabletargetaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json index 8ba87de8c90d0..b09e8af1ba116 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ApplicationInsights.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ApplicationInsights::Application.Alarm": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-applicationinsights-application-alarm.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json index 5e3a904ad5a2a..b16812d311319 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Athena.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Athena::WorkGroup.EncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-athena-workgroup-encryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json index bc1a5d1b53989..61d7a09f12a2f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AuditManager.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AuditManager::Assessment.AWSAccount": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-auditmanager-assessment-awsaccount.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json index 9c43095e9b581..3193038d3ee71 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScaling.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AutoScaling::AutoScalingGroup.AcceleratorCountRequest": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-autoscalinggroup-acceleratorcountrequest.html", @@ -857,6 +857,17 @@ "UpdateType": "Mutable" } } + }, + "AWS::AutoScaling::WarmPool.InstanceReusePolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-warmpool-instancereusepolicy.html", + "Properties": { + "ReuseOnScaleIn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscaling-warmpool-instancereusepolicy.html#cfn-autoscaling-warmpool-instancereusepolicy-reuseonscalein", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + } + } } }, "ResourceTypes": { @@ -1375,6 +1386,12 @@ "Required": true, "UpdateType": "Immutable" }, + "InstanceReusePolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-warmpool.html#cfn-autoscaling-warmpool-instancereusepolicy", + "Required": false, + "Type": "InstanceReusePolicy", + "UpdateType": "Mutable" + }, "MaxGroupPreparedCapacity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-autoscaling-warmpool.html#cfn-autoscaling-warmpool-maxgrouppreparedcapacity", "PrimitiveType": "Integer", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json index aea4ab907b61b..14964a920c478 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_AutoScalingPlans.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::AutoScalingPlans::ScalingPlan.ApplicationSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-autoscalingplans-scalingplan-applicationsource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json index 77977f9608c48..fef22afe7dd6e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Backup.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Backup::BackupPlan.AdvancedBackupSettingResourceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-backup-backupplan-advancedbackupsettingresourcetype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json index 44101f2061be2..17486408ef5a2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Batch.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Batch::ComputeEnvironment.ComputeResources": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json index c3a91feac2430..bd570f257e310 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Budgets.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Budgets::Budget.BudgetData": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-budgets-budget-budgetdata.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json index c845dd4d8257c..10ec09676d838 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CE.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CE::AnomalySubscription.Subscriber": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ce-anomalysubscription-subscriber.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json index 96712fa1540db..248d7f45762b8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CUR.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CUR::ReportDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json index 6514b1e6c3502..92e62f2abe62c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cassandra.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Cassandra::Table.BillingMode": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cassandra-table-billingmode.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json index 3c0a283eab7bc..89c119e8036fa 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CertificateManager.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CertificateManager::Account.ExpiryEventsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-certificatemanager-account-expiryeventsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json index 551b2a5b07d9e..26dbcd5632dc0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Chatbot.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Chatbot::SlackChannelConfiguration": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json index 3bfd4f76645eb..b5e0218b50999 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cloud9.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Cloud9::EnvironmentEC2.Repository": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloud9-environmentec2-repository.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json index 4bd9d2c6f43ea..505651a0bf526 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFormation.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CloudFormation::ResourceVersion.LoggingConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudformation-resourceversion-loggingconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json index 58decc870c5e3..379507c155bb3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudFront.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CloudFront::CachePolicy.CachePolicyConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-cachepolicy-cachepolicyconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json index f2c3e8cf57327..1aceb8d9e912a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudTrail.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CloudTrail::Trail.DataResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudtrail-trail-dataresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json index b647823545234..8b157900c704b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CloudWatch.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CloudWatch::Alarm.Dimension": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-dimension.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json index cd9fe58868013..120a64e210246 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeArtifact.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeArtifact::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json index 2d80bb05dd971..fcd07ab290568 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeBuild.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeBuild::Project.Artifacts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codebuild-project-artifacts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json index 5bcf4d3267ffc..541242d2ba064 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeCommit.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeCommit::Repository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codecommit-repository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json index 8daa134b5db39..cfbc56cecd081 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeDeploy.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeDeploy::DeploymentConfig.MinimumHealthyHosts": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codedeploy-deploymentconfig-minimumhealthyhosts.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json index 01b9fa402ef2d..9c7735ec4fc0e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruProfiler.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeGuruProfiler::ProfilingGroup.Channel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codeguruprofiler-profilinggroup-channel.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json index 262b69c5d8187..0f8ec67bec645 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeGuruReviewer.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeGuruReviewer::RepositoryAssociation": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json index d57d7264a14e6..bd180e3e81fcc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodePipeline.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodePipeline::CustomActionType.ArtifactDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codepipeline-customactiontype-artifactdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json index 34811ba5325e2..96f200ecd4e04 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStar.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeStar::GitHubRepository.Code": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestar-githubrepository-code.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json index 335ce16afd430..d4bc922519cff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarConnections.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::CodeStarConnections::Connection": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json index 2374007281db7..9d8fed731a9c8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CodeStarNotifications.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CodeStarNotifications::NotificationRule.Target": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-codestarnotifications-notificationrule-target.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json index 4eaeb23910578..5227cc1bbf620 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Cognito.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Cognito::IdentityPool.CognitoIdentityProvider": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cognito-identitypool-cognitoidentityprovider.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json index f85295ef6bbae..cb03eba8824de 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Config.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Config::ConfigRule.Scope": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-configrule-scope.html", @@ -185,6 +185,80 @@ } } }, + "AWS::Config::OrganizationConfigRule.OrganizationCustomCodeRuleMetadata": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html", + "Properties": { + "CodeText": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-codetext", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "DebugLogDeliveryAccounts": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-debuglogdeliveryaccounts", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "InputParameters": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-inputparameters", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "MaximumExecutionFrequency": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-maximumexecutionfrequency", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "OrganizationConfigRuleTriggerTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-organizationconfigruletriggertypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceIdScope": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-resourceidscope", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "ResourceTypesScope": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-resourcetypesscope", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Runtime": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-runtime", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "TagKeyScope": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-tagkeyscope", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "TagValueScope": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomcoderulemetadata.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata-tagvaluescope", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Config::OrganizationConfigRule.OrganizationCustomRuleMetadata": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-config-organizationconfigrule-organizationcustomrulemetadata.html", "Properties": { @@ -629,6 +703,12 @@ "Required": true, "UpdateType": "Immutable" }, + "OrganizationCustomCodeRuleMetadata": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-config-organizationconfigrule.html#cfn-config-organizationconfigrule-organizationcustomcoderulemetadata", + "Required": false, + "Type": "OrganizationCustomCodeRuleMetadata", + "UpdateType": "Mutable" + }, "OrganizationCustomRuleMetadata": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-config-organizationconfigrule.html#cfn-config-organizationconfigrule-organizationcustomrulemetadata", "Required": false, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json index 3cc5b84d16b49..469b6626393cf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Connect.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Connect::HoursOfOperation.HoursOfOperationConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-connect-hoursofoperation-hoursofoperationconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json index 161c0c9be0e0c..23161e2b2dec5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_CustomerProfiles.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::CustomerProfiles::Integration.ConnectorOperator": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-customerprofiles-integration-connectoroperator.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json index 0976d67b62ddb..79500a3d00a45 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DAX.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DAX::Cluster.SSESpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dax-cluster-ssespecification.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json index f2e70234d08ad..cd5782c6e5f5f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DLM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DLM::LifecyclePolicy.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dlm-lifecyclepolicy-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json index 5276f2f91da55..ffe692258dc0d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DMS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DMS::Endpoint.DocDbSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dms-endpoint-docdbsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json index caf8ded62e758..a5886268c2d16 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataBrew.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DataBrew::Dataset.CsvOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-databrew-dataset-csvoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json index 24401d66d6908..3a4165f28ac4b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataPipeline.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DataPipeline::Pipeline.Field": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datapipeline-pipeline-pipelineobjects-fields.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json index 47e807718de45..3bea1482dc65b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DataSync.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DataSync::LocationEFS.Ec2Config": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-datasync-locationefs-ec2config.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json index 6fbae0972f88d..6f23538af7616 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Detective.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Detective::Graph": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json index 729518e4850bc..606d19bf8ccda 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DevOpsGuru.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DevOpsGuru::NotificationChannel.NotificationChannelConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-devopsguru-notificationchannel-notificationchannelconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json index 3460e06ec7729..ff40ca6d13a97 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DirectoryService.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DirectoryService::MicrosoftAD.VpcSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-directoryservice-microsoftad-vpcsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json index e3ef6d0414a90..7724c6b92277a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DocDB.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::DocDB::DBCluster": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json index d948da8ac30fe..fce8b13b3c4ab 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_DynamoDB.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::DynamoDB::GlobalTable.AttributeDefinition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-globaltable-attributedefinition.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json index 029236531fb32..dd378cad166e2 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EC2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EC2::CapacityReservation.TagSpecification": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-capacityreservation-tagspecification.html", @@ -142,6 +142,23 @@ } } }, + "AWS::EC2::ClientVpnEndpoint.ClientLoginBannerOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-clientvpnendpoint-clientloginbanneroptions.html", + "Properties": { + "BannerText": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-clientvpnendpoint-clientloginbanneroptions.html#cfn-ec2-clientvpnendpoint-clientloginbanneroptions-bannertext", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Enabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-clientvpnendpoint-clientloginbanneroptions.html#cfn-ec2-clientvpnendpoint-clientloginbanneroptions-enabled", + "PrimitiveType": "Boolean", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::EC2::ClientVpnEndpoint.ConnectionLogOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-clientvpnendpoint-connectionlogoptions.html", "Properties": { @@ -1469,6 +1486,144 @@ } } }, + "AWS::EC2::LaunchTemplate.InstanceRequirements": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html", + "Properties": { + "AcceleratorCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-acceleratorcount", + "Required": false, + "Type": "AcceleratorCount", + "UpdateType": "Mutable" + }, + "AcceleratorManufacturers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-acceleratormanufacturers", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AcceleratorNames": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-acceleratornames", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AcceleratorTotalMemoryMiB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-acceleratortotalmemorymib", + "Required": false, + "Type": "AcceleratorTotalMemoryMiB", + "UpdateType": "Mutable" + }, + "AcceleratorTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-acceleratortypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "BareMetal": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-baremetal", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "BaselineEbsBandwidthMbps": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-baselineebsbandwidthmbps", + "Required": false, + "Type": "BaselineEbsBandwidthMbps", + "UpdateType": "Mutable" + }, + "BurstablePerformance": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-burstableperformance", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "CpuManufacturers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-cpumanufacturers", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ExcludedInstanceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-excludedinstancetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "InstanceGenerations": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-instancegenerations", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "LocalStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-localstorage", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "LocalStorageTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-localstoragetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "MemoryGiBPerVCpu": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-memorygibpervcpu", + "Required": false, + "Type": "MemoryGiBPerVCpu", + "UpdateType": "Mutable" + }, + "MemoryMiB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-memorymib", + "Required": false, + "Type": "MemoryMiB", + "UpdateType": "Mutable" + }, + "NetworkInterfaceCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-networkinterfacecount", + "Required": false, + "Type": "NetworkInterfaceCount", + "UpdateType": "Mutable" + }, + "OnDemandMaxPricePercentageOverLowestPrice": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-ondemandmaxpricepercentageoverlowestprice", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "RequireHibernateSupport": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-requirehibernatesupport", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "SpotMaxPricePercentageOverLowestPrice": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-spotmaxpricepercentageoverlowestprice", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "TotalLocalStorageGB": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-totallocalstoragegb", + "Required": false, + "Type": "TotalLocalStorageGB", + "UpdateType": "Mutable" + }, + "VCpuCount": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata-instancerequirements.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements-vcpucount", + "Required": false, + "Type": "VCpuCount", + "UpdateType": "Mutable" + } + } + }, "AWS::EC2::LaunchTemplate.Ipv6Add": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-ipv6add.html", "Properties": { @@ -1570,6 +1725,12 @@ "Type": "InstanceMarketOptions", "UpdateType": "Mutable" }, + "InstanceRequirements": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-instancerequirements", + "Required": false, + "Type": "InstanceRequirements", + "UpdateType": "Mutable" + }, "InstanceType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-launchtemplatedata.html#cfn-ec2-launchtemplate-launchtemplatedata-instancetype", "PrimitiveType": "String", @@ -2081,6 +2242,131 @@ } } }, + "AWS::EC2::NetworkInsightsAccessScope.AccessScopePathRequest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-accessscopepathrequest.html", + "Properties": { + "Destination": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-accessscopepathrequest.html#cfn-ec2-networkinsightsaccessscope-accessscopepathrequest-destination", + "Required": false, + "Type": "PathStatementRequest", + "UpdateType": "Immutable" + }, + "Source": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-accessscopepathrequest.html#cfn-ec2-networkinsightsaccessscope-accessscopepathrequest-source", + "Required": false, + "Type": "PathStatementRequest", + "UpdateType": "Immutable" + }, + "ThroughResources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-accessscopepathrequest.html#cfn-ec2-networkinsightsaccessscope-accessscopepathrequest-throughresources", + "ItemType": "ThroughResourcesStatementRequest", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::EC2::NetworkInsightsAccessScope.PacketHeaderStatementRequest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html", + "Properties": { + "DestinationAddresses": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-destinationaddresses", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "DestinationPorts": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-destinationports", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "DestinationPrefixLists": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-destinationprefixlists", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Protocols": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-protocols", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "SourceAddresses": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-sourceaddresses", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "SourcePorts": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-sourceports", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "SourcePrefixLists": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-packetheaderstatementrequest.html#cfn-ec2-networkinsightsaccessscope-packetheaderstatementrequest-sourceprefixlists", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::EC2::NetworkInsightsAccessScope.PathStatementRequest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-pathstatementrequest.html", + "Properties": { + "PacketHeaderStatement": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-pathstatementrequest.html#cfn-ec2-networkinsightsaccessscope-pathstatementrequest-packetheaderstatement", + "Required": false, + "Type": "PacketHeaderStatementRequest", + "UpdateType": "Immutable" + }, + "ResourceStatement": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-pathstatementrequest.html#cfn-ec2-networkinsightsaccessscope-pathstatementrequest-resourcestatement", + "Required": false, + "Type": "ResourceStatementRequest", + "UpdateType": "Immutable" + } + } + }, + "AWS::EC2::NetworkInsightsAccessScope.ResourceStatementRequest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-resourcestatementrequest.html", + "Properties": { + "ResourceTypes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-resourcestatementrequest.html#cfn-ec2-networkinsightsaccessscope-resourcestatementrequest-resourcetypes", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Resources": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-resourcestatementrequest.html#cfn-ec2-networkinsightsaccessscope-resourcestatementrequest-resources", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + } + } + }, + "AWS::EC2::NetworkInsightsAccessScope.ThroughResourcesStatementRequest": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-throughresourcesstatementrequest.html", + "Properties": { + "ResourceStatement": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsaccessscope-throughresourcesstatementrequest.html#cfn-ec2-networkinsightsaccessscope-throughresourcesstatementrequest-resourcestatement", + "Required": false, + "Type": "ResourceStatementRequest", + "UpdateType": "Immutable" + } + } + }, "AWS::EC2::NetworkInsightsAnalysis.AlternatePathHint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-networkinsightsanalysis-alternatepathhint.html", "Properties": { @@ -4163,6 +4449,12 @@ "Type": "ClientConnectOptions", "UpdateType": "Mutable" }, + "ClientLoginBannerOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnendpoint.html#cfn-ec2-clientvpnendpoint-clientloginbanneroptions", + "Required": false, + "Type": "ClientLoginBannerOptions", + "UpdateType": "Mutable" + }, "ConnectionLogOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnendpoint.html#cfn-ec2-clientvpnendpoint-connectionlogoptions", "Required": true, @@ -4201,6 +4493,12 @@ "Required": true, "UpdateType": "Mutable" }, + "SessionTimeoutHours": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnendpoint.html#cfn-ec2-clientvpnendpoint-sessiontimeouthours", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "SplitTunnel": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-clientvpnendpoint.html#cfn-ec2-clientvpnendpoint-splittunnel", "PrimitiveType": "Boolean", @@ -4580,6 +4878,12 @@ "Required": false, "UpdateType": "Immutable" }, + "DestinationOptions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-flowlog.html#cfn-ec2-flowlog-destinationoptions", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Immutable" + }, "LogDestination": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-flowlog.html#cfn-ec2-flowlog-logdestination", "PrimitiveType": "String", @@ -4661,6 +4965,11 @@ } }, "AWS::EC2::Host": { + "Attributes": { + "HostId": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-host.html", "Properties": { "AutoPlacement": { @@ -4893,6 +5202,9 @@ "IpamScopeId": { "PrimitiveType": "String" }, + "IpamScopeType": { + "PrimitiveType": "String" + }, "IsDefault": { "PrimitiveType": "Boolean" }, @@ -4914,12 +5226,6 @@ "Required": true, "UpdateType": "Immutable" }, - "IpamScopeType": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html#cfn-ec2-ipamscope-ipamscopetype", - "PrimitiveType": "String", - "Required": false, - "UpdateType": "Immutable" - }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-ipamscope.html#cfn-ec2-ipamscope-tags", "DuplicatesAllowed": false, @@ -5444,6 +5750,90 @@ } } }, + "AWS::EC2::NetworkInsightsAccessScope": { + "Attributes": { + "CreatedDate": { + "PrimitiveType": "String" + }, + "NetworkInsightsAccessScopeArn": { + "PrimitiveType": "String" + }, + "NetworkInsightsAccessScopeId": { + "PrimitiveType": "String" + }, + "UpdatedDate": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscope.html", + "Properties": { + "ExcludePaths": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscope.html#cfn-ec2-networkinsightsaccessscope-excludepaths", + "ItemType": "AccessScopePathRequest", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "MatchPaths": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscope.html#cfn-ec2-networkinsightsaccessscope-matchpaths", + "ItemType": "AccessScopePathRequest", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscope.html#cfn-ec2-networkinsightsaccessscope-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::EC2::NetworkInsightsAccessScopeAnalysis": { + "Attributes": { + "AnalyzedEniCount": { + "PrimitiveType": "Integer" + }, + "EndDate": { + "PrimitiveType": "String" + }, + "FindingsFound": { + "PrimitiveType": "String" + }, + "NetworkInsightsAccessScopeAnalysisArn": { + "PrimitiveType": "String" + }, + "NetworkInsightsAccessScopeAnalysisId": { + "PrimitiveType": "String" + }, + "StartDate": { + "PrimitiveType": "String" + }, + "Status": { + "PrimitiveType": "String" + }, + "StatusMessage": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscopeanalysis.html", + "Properties": { + "NetworkInsightsAccessScopeId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscopeanalysis.html#cfn-ec2-networkinsightsaccessscopeanalysis-networkinsightsaccessscopeid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-networkinsightsaccessscopeanalysis.html#cfn-ec2-networkinsightsaccessscopeanalysis-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::EC2::NetworkInsightsAnalysis": { "Attributes": { "AlternatePathHints": { @@ -7334,10 +7724,15 @@ } }, "AWS::EC2::VPNGatewayRoutePropagation": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html", + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html", "Properties": { "RouteTableIds": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html#cfn-ec2-vpngatewayrouteprop-routetableids", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html#cfn-ec2-vpngatewayroutepropagation-routetableids", "DuplicatesAllowed": true, "PrimitiveItemType": "String", "Required": true, @@ -7345,7 +7740,7 @@ "UpdateType": "Mutable" }, "VpnGatewayId": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpn-gatewayrouteprop.html#cfn-ec2-vpngatewayrouteprop-vpngatewayid", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpngatewayroutepropagation.html#cfn-ec2-vpngatewayroutepropagation-vpngatewayid", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json index 02fcf1110ec4d..d252878b0d862 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ECR.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ECR::ReplicationConfiguration.ReplicationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecr-replicationconfiguration-replicationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json index 203a10c8ecad9..ee85713d3e080 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EFS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EFS::AccessPoint.AccessPointTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-efs-accesspoint-accesspointtag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json index e051d03d82d22..f45918127ad5d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EKS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EKS::Cluster.ClusterLogging": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eks-cluster-clusterlogging.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json index 1efac6ff55966..d7b325eb529df 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMR.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EMR::Cluster.Application": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticmapreduce-cluster-application.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json index eaed9da59e333..f60c93ac0c948 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EMRContainers.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EMRContainers::VirtualCluster.ContainerInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-emrcontainers-virtualcluster-containerinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json index b42c9124e8865..f767bf251126a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElastiCache.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ElastiCache::CacheCluster.CloudWatchLogsDestinationDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticache-cachecluster-cloudwatchlogsdestinationdetails.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json index eeecbd98e2da7..2096de48abd48 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticBeanstalk.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ElasticBeanstalk::Application.ApplicationResourceLifecycleConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticbeanstalk-application-applicationresourcelifecycleconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json index 5f1a7e6239094..c8525a1258f6c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancing.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancing::LoadBalancer.AccessLoggingPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-elb-accessloggingpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json index f69dbb286de7e..caf56c1ab64a8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ElasticLoadBalancingV2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ElasticLoadBalancingV2::Listener.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json index af467b0f95f95..9d70be4cb4ef5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Elasticsearch.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Elasticsearch::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticsearch-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json index 67a5730b33d03..c65bbf2e449a1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_EventSchemas.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::EventSchemas::Discoverer.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-eventschemas-discoverer-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json index c95cdfeb22e6a..91b7b7e8343b8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Events.json @@ -1,6 +1,23 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { + "AWS::Events::EventBus.TagEntry": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-eventbus-tagentry.html", + "Properties": { + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-eventbus-tagentry.html#cfn-events-eventbus-tagentry-key", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-eventbus-tagentry.html#cfn-events-eventbus-tagentry-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, "AWS::Events::EventBusPolicy.Condition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-events-eventbuspolicy-condition.html", "Properties": { @@ -703,6 +720,13 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-eventbus.html#cfn-events-eventbus-tags", + "ItemType": "TagEntry", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" } } }, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json index 67002e39a1f7e..efaef09a38170 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Evidently.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Evidently::Experiment.MetricGoalObject": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-evidently-experiment-metricgoalobject.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json index 9d7ddbe36cf2f..00062927b9490 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FIS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::FIS::ExperimentTemplate.ExperimentTemplateAction": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fis-experimenttemplate-experimenttemplateaction.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json index c571c6477ec36..533b85ab0a40c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FMS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::FMS::Policy.IEMap": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fms-policy-iemap.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json index 546d2cc9afd10..77b7021c2d7bc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FSx.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::FSx::FileSystem.AuditLogConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-fsx-filesystem-windowsconfiguration-auditlogconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json index db128afd96461..4e608724558b5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FinSpace.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::FinSpace::Environment.FederationParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-finspace-environment-federationparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json new file mode 100644 index 0000000000000..8c024f102368a --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Forecast.json @@ -0,0 +1,95 @@ +{ + "$version": "53.0.0", + "PropertyTypes": {}, + "ResourceTypes": { + "AWS::Forecast::Dataset": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html", + "Properties": { + "DataFrequency": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-datafrequency", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "DatasetName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-datasetname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "DatasetType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-datasettype", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Domain": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-domain", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "EncryptionConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-encryptionconfig", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, + "Schema": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-schema", + "PrimitiveType": "Json", + "Required": true, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-dataset.html#cfn-forecast-dataset-tags", + "PrimitiveItemType": "Json", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Forecast::DatasetGroup": { + "Attributes": { + "DatasetGroupArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-datasetgroup.html", + "Properties": { + "DatasetArns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-datasetgroup.html#cfn-forecast-datasetgroup-datasetarns", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "DatasetGroupName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-datasetgroup.html#cfn-forecast-datasetgroup-datasetgroupname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "Domain": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-datasetgroup.html#cfn-forecast-datasetgroup-domain", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-forecast-datasetgroup.html#cfn-forecast-datasetgroup-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json index 861094a8d1426..780b6537e27bd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_FraudDetector.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::FraudDetector::Detector.EntityType": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-frauddetector-detector-entitytype.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json index aecfdc02cebe3..024232d7655f7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GameLift.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::GameLift::Alias.RoutingStrategy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-gamelift-alias-routingstrategy.html", @@ -699,6 +699,13 @@ "Type": "PriorityConfiguration", "UpdateType": "Mutable" }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-gamesessionqueue.html#cfn-gamelift-gamesessionqueue-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "TimeoutInSeconds": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-gamesessionqueue.html#cfn-gamelift-gamesessionqueue-timeoutinseconds", "PrimitiveType": "Integer", @@ -803,6 +810,13 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-matchmakingconfiguration.html#cfn-gamelift-matchmakingconfiguration-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" } } }, @@ -828,6 +842,13 @@ "PrimitiveType": "String", "Required": true, "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-matchmakingruleset.html#cfn-gamelift-matchmakingruleset-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" } } }, @@ -854,6 +875,13 @@ "Type": "S3Location", "UpdateType": "Mutable" }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-script.html#cfn-gamelift-script-tags", + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "Version": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-gamelift-script.html#cfn-gamelift-script-version", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json index 297f342d67056..c26531868dfa8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GlobalAccelerator.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::GlobalAccelerator::EndpointGroup.EndpointConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-globalaccelerator-endpointgroup-endpointconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json index fd2957ddc0e39..3195c26628fcf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Glue.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Glue::Classifier.CsvClassifier": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-classifier-csvclassifier.html", @@ -237,6 +237,23 @@ } } }, + "AWS::Glue::Crawler.MongoDBTarget": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-mongodbtarget.html", + "Properties": { + "ConnectionName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-mongodbtarget.html#cfn-glue-crawler-mongodbtarget-connectionname", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Path": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-mongodbtarget.html#cfn-glue-crawler-mongodbtarget-path", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Glue::Crawler.RecrawlPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-recrawlpolicy.html", "Properties": { @@ -257,6 +274,18 @@ "Required": false, "UpdateType": "Mutable" }, + "DlqEventQueueArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-s3target.html#cfn-glue-crawler-s3target-dlqeventqueuearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "EventQueueArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-s3target.html#cfn-glue-crawler-s3target-eventqueuearn", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "Exclusions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-s3target.html#cfn-glue-crawler-s3target-exclusions", "PrimitiveItemType": "String", @@ -269,6 +298,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "SampleSize": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-s3target.html#cfn-glue-crawler-s3target-samplesize", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" } } }, @@ -324,6 +359,13 @@ "Type": "List", "UpdateType": "Mutable" }, + "MongoDBTargets": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-targets.html#cfn-glue-crawler-targets-mongodbtargets", + "ItemType": "MongoDBTarget", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, "S3Targets": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-glue-crawler-targets.html#cfn-glue-crawler-targets-s3targets", "ItemType": "S3Target", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json index 0fa105153b10f..ea6290026de34 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Greengrass.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Greengrass::ConnectorDefinition.Connector": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-connectordefinition-connector.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json index bdafce1241adb..1cfba354f55cb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GreengrassV2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::GreengrassV2::ComponentVersion.ComponentDependencyRequirement": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrassv2-componentversion-componentdependencyrequirement.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json index 0df34b7bb7808..ee891e28da1bf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GroundStation.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::GroundStation::Config.AntennaDownlinkConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-groundstation-config-antennadownlinkconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json index ab6824be6e9ea..c74e38b2707b1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_GuardDuty.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::GuardDuty::Detector.CFNDataSourceConfigurations": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-guardduty-detector-cfndatasourceconfigurations.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json index a0f20a542876e..184183403c5eb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_HealthLake.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::HealthLake::FHIRDatastore.KmsEncryptionConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-healthlake-fhirdatastore-kmsencryptionconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json index 60c268330a901..aea05b1dfe0db 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IAM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IAM::Group.Policy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-policy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json index ab81fecb7c027..2372f426bbdb3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IVS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IVS::RecordingConfiguration.DestinationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ivs-recordingconfiguration-destinationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json index 333abcdb0b80e..34a6a66cf5ed6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ImageBuilder.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ImageBuilder::ContainerRecipe.ComponentConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-imagebuilder-containerrecipe-componentconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json index a5e6752d83dd9..8e6d7a60b39f8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Inspector.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Inspector::AssessmentTarget": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json new file mode 100644 index 0000000000000..f798592860c06 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_InspectorV2.json @@ -0,0 +1,395 @@ +{ + "$version": "53.0.0", + "PropertyTypes": { + "AWS::InspectorV2::Filter.DateFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html", + "Properties": { + "EndInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html#cfn-inspectorv2-filter-datefilter-endinclusive", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "StartInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-datefilter.html#cfn-inspectorv2-filter-datefilter-startinclusive", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.FilterCriteria": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html", + "Properties": { + "AwsAccountId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-awsaccountid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ComponentId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-componentid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ComponentType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-componenttype", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Ec2InstanceImageId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ec2instanceimageid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Ec2InstanceSubnetId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ec2instancesubnetid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Ec2InstanceVpcId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ec2instancevpcid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImageArchitecture": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimagearchitecture", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImageHash": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimagehash", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImagePushedAt": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimagepushedat", + "ItemType": "DateFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImageRegistry": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimageregistry", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImageRepositoryName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimagerepositoryname", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "EcrImageTags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-ecrimagetags", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "FindingArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-findingarn", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "FindingStatus": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-findingstatus", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "FindingType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-findingtype", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "FirstObservedAt": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-firstobservedat", + "ItemType": "DateFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "InspectorScore": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-inspectorscore", + "ItemType": "NumberFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "LastObservedAt": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-lastobservedat", + "ItemType": "DateFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "NetworkProtocol": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-networkprotocol", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "PortRange": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-portrange", + "ItemType": "PortRangeFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "RelatedVulnerabilities": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-relatedvulnerabilities", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-resourceid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceTags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-resourcetags", + "ItemType": "MapFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourceType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-resourcetype", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Severity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-severity", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Title": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-title", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "UpdatedAt": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-updatedat", + "ItemType": "DateFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "VendorSeverity": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-vendorseverity", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "VulnerabilityId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-vulnerabilityid", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "VulnerabilitySource": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-vulnerabilitysource", + "ItemType": "StringFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "VulnerablePackages": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-filtercriteria.html#cfn-inspectorv2-filter-filtercriteria-vulnerablepackages", + "ItemType": "PackageFilter", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.MapFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-mapfilter.html", + "Properties": { + "Comparison": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-mapfilter.html#cfn-inspectorv2-filter-mapfilter-comparison", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Key": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-mapfilter.html#cfn-inspectorv2-filter-mapfilter-key", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-mapfilter.html#cfn-inspectorv2-filter-mapfilter-value", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.NumberFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-numberfilter.html", + "Properties": { + "LowerInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-numberfilter.html#cfn-inspectorv2-filter-numberfilter-lowerinclusive", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "UpperInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-numberfilter.html#cfn-inspectorv2-filter-numberfilter-upperinclusive", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.PackageFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html", + "Properties": { + "Architecture": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-architecture", + "Required": false, + "Type": "StringFilter", + "UpdateType": "Mutable" + }, + "Epoch": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-epoch", + "Required": false, + "Type": "NumberFilter", + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-name", + "Required": false, + "Type": "StringFilter", + "UpdateType": "Mutable" + }, + "Release": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-release", + "Required": false, + "Type": "StringFilter", + "UpdateType": "Mutable" + }, + "SourceLayerHash": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-sourcelayerhash", + "Required": false, + "Type": "StringFilter", + "UpdateType": "Mutable" + }, + "Version": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-packagefilter.html#cfn-inspectorv2-filter-packagefilter-version", + "Required": false, + "Type": "StringFilter", + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.PortRangeFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-portrangefilter.html", + "Properties": { + "BeginInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-portrangefilter.html#cfn-inspectorv2-filter-portrangefilter-begininclusive", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "EndInclusive": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-portrangefilter.html#cfn-inspectorv2-filter-portrangefilter-endinclusive", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::InspectorV2::Filter.StringFilter": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-stringfilter.html", + "Properties": { + "Comparison": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-stringfilter.html#cfn-inspectorv2-filter-stringfilter-comparison", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "Value": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-inspectorv2-filter-stringfilter.html#cfn-inspectorv2-filter-stringfilter-value", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + } + }, + "ResourceTypes": { + "AWS::InspectorV2::Filter": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-inspectorv2-filter.html", + "Properties": { + "Description": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-inspectorv2-filter.html#cfn-inspectorv2-filter-description", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "FilterAction": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-inspectorv2-filter.html#cfn-inspectorv2-filter-filteraction", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "FilterCriteria": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-inspectorv2-filter.html#cfn-inspectorv2-filter-filtercriteria", + "Required": true, + "Type": "FilterCriteria", + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-inspectorv2-filter.html#cfn-inspectorv2-filter-name", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json index ab0a274500ab1..832964ade69ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoT::AccountAuditConfiguration.AuditCheckConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot-accountauditconfiguration-auditcheckconfiguration.html", @@ -1952,6 +1952,12 @@ "Required": false, "UpdateType": "Immutable" }, + "JobExecutionsRetryConfig": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iot-jobtemplate.html#cfn-iot-jobtemplate-jobexecutionsretryconfig", + "PrimitiveType": "Json", + "Required": false, + "UpdateType": "Mutable" + }, "JobExecutionsRolloutConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iot-jobtemplate.html#cfn-iot-jobtemplate-jobexecutionsrolloutconfig", "PrimitiveType": "Json", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json index 68c4bd9063204..8bc663da25fe7 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoT1Click.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoT1Click::Project.DeviceTemplate": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iot1click-project-devicetemplate.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json index 08043644d063e..dde9b516dd10f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoTAnalytics::Channel.ChannelStorage": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-channelstorage.html", @@ -59,8 +59,7 @@ } }, "AWS::IoTAnalytics::Channel.ServiceManagedS3": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-servicemanageds3.html", - "Properties": {} + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-channel-servicemanageds3.html" }, "AWS::IoTAnalytics::Dataset.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-action.html", @@ -108,6 +107,7 @@ }, "Variables": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-containeraction.html#cfn-iotanalytics-dataset-containeraction-variables", + "DuplicatesAllowed": true, "ItemType": "Variable", "Required": false, "Type": "List", @@ -150,12 +150,12 @@ } }, "AWS::IoTAnalytics::Dataset.DatasetContentVersionValue": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-datasetcontentversionvalue.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-datasetcontentversionvalue.html", "Properties": { "DatasetName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-datasetcontentversionvalue.html#cfn-iotanalytics-dataset-variable-datasetcontentversionvalue-datasetname", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-datasetcontentversionvalue.html#cfn-iotanalytics-dataset-datasetcontentversionvalue-datasetname", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -262,12 +262,12 @@ } }, "AWS::IoTAnalytics::Dataset.OutputFileUriValue": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-outputfileurivalue.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-outputfileurivalue.html", "Properties": { "FileName": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-variable-outputfileurivalue.html#cfn-iotanalytics-dataset-variable-outputfileurivalue-filename", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-outputfileurivalue.html#cfn-iotanalytics-dataset-outputfileurivalue-filename", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -277,6 +277,7 @@ "Properties": { "Filters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-queryaction.html#cfn-iotanalytics-dataset-queryaction-filters", + "DuplicatesAllowed": true, "ItemType": "Filter", "Required": false, "Type": "List", @@ -354,10 +355,10 @@ } }, "AWS::IoTAnalytics::Dataset.Schedule": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-trigger-schedule.html", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-schedule.html", "Properties": { "ScheduleExpression": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-trigger-schedule.html#cfn-iotanalytics-dataset-trigger-schedule-scheduleexpression", + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-dataset-schedule.html#cfn-iotanalytics-dataset-schedule-scheduleexpression", "PrimitiveType": "String", "Required": true, "UpdateType": "Mutable" @@ -523,6 +524,7 @@ "Properties": { "Partitions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-datastorepartitions.html#cfn-iotanalytics-datastore-datastorepartitions-partitions", + "DuplicatesAllowed": true, "ItemType": "DatastorePartition", "Required": false, "Type": "List", @@ -575,15 +577,14 @@ "Properties": { "CustomerManagedS3Storage": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-iotsitewisemultilayerstorage.html#cfn-iotanalytics-datastore-iotsitewisemultilayerstorage-customermanageds3storage", - "Required": true, + "Required": false, "Type": "CustomerManagedS3Storage", "UpdateType": "Mutable" } } }, "AWS::IoTAnalytics::Datastore.JsonConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-jsonconfiguration.html", - "Properties": {} + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-jsonconfiguration.html" }, "AWS::IoTAnalytics::Datastore.ParquetConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-parquetconfiguration.html", @@ -629,6 +630,7 @@ "Properties": { "Columns": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-schemadefinition.html#cfn-iotanalytics-datastore-schemadefinition-columns", + "DuplicatesAllowed": true, "ItemType": "Column", "Required": false, "Type": "List", @@ -637,8 +639,7 @@ } }, "AWS::IoTAnalytics::Datastore.ServiceManagedS3": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-servicemanageds3.html", - "Properties": {} + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-servicemanageds3.html" }, "AWS::IoTAnalytics::Datastore.TimestampPartition": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-datastore-timestamppartition.html", @@ -727,14 +728,15 @@ "Properties": { "Attributes": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-addattributes.html#cfn-iotanalytics-pipeline-addattributes-attributes", - "PrimitiveType": "Json", - "Required": false, + "PrimitiveItemType": "String", + "Required": true, + "Type": "Map", "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-addattributes.html#cfn-iotanalytics-pipeline-addattributes-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -751,13 +753,13 @@ "ChannelName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-channel.html#cfn-iotanalytics-pipeline-channel-channelname", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-channel.html#cfn-iotanalytics-pipeline-channel-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -774,13 +776,13 @@ "DatastoreName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-datastore.html#cfn-iotanalytics-pipeline-datastore-datastorename", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-datastore.html#cfn-iotanalytics-pipeline-datastore-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -791,13 +793,13 @@ "Attribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceregistryenrich.html#cfn-iotanalytics-pipeline-deviceregistryenrich-attribute", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceregistryenrich.html#cfn-iotanalytics-pipeline-deviceregistryenrich-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -809,13 +811,13 @@ "RoleArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceregistryenrich.html#cfn-iotanalytics-pipeline-deviceregistryenrich-rolearn", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "ThingName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceregistryenrich.html#cfn-iotanalytics-pipeline-deviceregistryenrich-thingname", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -826,13 +828,13 @@ "Attribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceshadowenrich.html#cfn-iotanalytics-pipeline-deviceshadowenrich-attribute", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceshadowenrich.html#cfn-iotanalytics-pipeline-deviceshadowenrich-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -844,13 +846,13 @@ "RoleArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceshadowenrich.html#cfn-iotanalytics-pipeline-deviceshadowenrich-rolearn", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "ThingName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-deviceshadowenrich.html#cfn-iotanalytics-pipeline-deviceshadowenrich-thingname", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -861,13 +863,13 @@ "Filter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-filter.html#cfn-iotanalytics-pipeline-filter-filter", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-filter.html#cfn-iotanalytics-pipeline-filter-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -884,19 +886,19 @@ "BatchSize": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-lambda.html#cfn-iotanalytics-pipeline-lambda-batchsize", "PrimitiveType": "Integer", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "LambdaName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-lambda.html#cfn-iotanalytics-pipeline-lambda-lambdaname", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-lambda.html#cfn-iotanalytics-pipeline-lambda-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -913,19 +915,19 @@ "Attribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-math.html#cfn-iotanalytics-pipeline-math-attribute", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Math": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-math.html#cfn-iotanalytics-pipeline-math-math", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-math.html#cfn-iotanalytics-pipeline-math-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -943,14 +945,14 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-removeattributes.html#cfn-iotanalytics-pipeline-removeattributes-attributes", "DuplicatesAllowed": true, "PrimitiveItemType": "String", - "Required": false, + "Required": true, "Type": "List", "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-removeattributes.html#cfn-iotanalytics-pipeline-removeattributes-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -968,14 +970,14 @@ "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-selectattributes.html#cfn-iotanalytics-pipeline-selectattributes-attributes", "DuplicatesAllowed": true, "PrimitiveItemType": "String", - "Required": false, + "Required": true, "Type": "List", "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotanalytics-pipeline-selectattributes.html#cfn-iotanalytics-pipeline-selectattributes-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Next": { @@ -989,6 +991,11 @@ }, "ResourceTypes": { "AWS::IoTAnalytics::Channel": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-channel.html", "Properties": { "ChannelName": { @@ -1011,6 +1018,7 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-channel.html#cfn-iotanalytics-channel-tags", + "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, "Type": "List", @@ -1019,10 +1027,16 @@ } }, "AWS::IoTAnalytics::Dataset": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html", "Properties": { "Actions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html#cfn-iotanalytics-dataset-actions", + "DuplicatesAllowed": true, "ItemType": "Action", "Required": true, "Type": "List", @@ -1030,6 +1044,7 @@ }, "ContentDeliveryRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html#cfn-iotanalytics-dataset-contentdeliveryrules", + "DuplicatesAllowed": true, "ItemType": "DatasetContentDeliveryRule", "Required": false, "Type": "List", @@ -1043,6 +1058,7 @@ }, "LateDataRules": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html#cfn-iotanalytics-dataset-latedatarules", + "DuplicatesAllowed": true, "ItemType": "LateDataRule", "Required": false, "Type": "List", @@ -1056,6 +1072,7 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html#cfn-iotanalytics-dataset-tags", + "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, "Type": "List", @@ -1063,6 +1080,7 @@ }, "Triggers": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-dataset.html#cfn-iotanalytics-dataset-triggers", + "DuplicatesAllowed": true, "ItemType": "Trigger", "Required": false, "Type": "List", @@ -1077,6 +1095,11 @@ } }, "AWS::IoTAnalytics::Datastore": { + "Attributes": { + "Id": { + "PrimitiveType": "String" + } + }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-datastore.html", "Properties": { "DatastoreName": { @@ -1111,6 +1134,7 @@ }, "Tags": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iotanalytics-datastore.html#cfn-iotanalytics-datastore-tags", + "DuplicatesAllowed": true, "ItemType": "Tag", "Required": false, "Type": "List", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json index 33c5ed7118618..79a0efcceac8e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTCoreDeviceAdvisor.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTCoreDeviceAdvisor::SuiteDefinition": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json index d324214079d98..97ae22098ae67 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTEvents.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoTEvents::DetectorModel.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotevents-detectormodel-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json index 839260e26e193..91e7831e64391 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTFleetHub.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::IoTFleetHub::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json index 6947456a73779..4528134d4e651 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTSiteWise.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoTSiteWise::AccessPolicy.AccessPolicyIdentity": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-accesspolicy-accesspolicyidentity.html", @@ -396,9 +396,15 @@ "Properties": { "Greengrass": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-gateway-gatewayplatform.html#cfn-iotsitewise-gateway-gatewayplatform-greengrass", - "Required": true, + "Required": false, "Type": "Greengrass", "UpdateType": "Immutable" + }, + "GreengrassV2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-gateway-gatewayplatform.html#cfn-iotsitewise-gateway-gatewayplatform-greengrassv2", + "Required": false, + "Type": "GreengrassV2", + "UpdateType": "Immutable" } } }, @@ -412,6 +418,17 @@ "UpdateType": "Immutable" } } + }, + "AWS::IoTSiteWise::Gateway.GreengrassV2": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-gateway-greengrassv2.html", + "Properties": { + "CoreDeviceThingName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotsitewise-gateway-greengrassv2.html#cfn-iotsitewise-gateway-greengrassv2-coredevicethingname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } } }, "ResourceTypes": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json index ba4ff225e79f2..808b194446d0a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTThingsGraph.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoTThingsGraph::FlowTemplate.DefinitionDocument": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotthingsgraph-flowtemplate-definitiondocument.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json index 7a74fee371eb8..7fea2730d7263 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_IoTWireless.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::IoTWireless::DeviceProfile.LoRaWANDeviceProfile": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iotwireless-deviceprofile-lorawandeviceprofile.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json index dccc1229fc1c2..f9a0ed9ee36ad 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KMS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::KMS::Alias": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json index 8b7a644d13bea..2d45b9f78beff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kendra.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Kendra::DataSource.AccessControlListConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kendra-datasource-accesscontrollistconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json index 5adc18f973763..c8d7dfddb2376 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Kinesis.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Kinesis::Stream.StreamEncryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesis-stream-streamencryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json index 43cc269ee6ee0..7b3d93fdd7fc1 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalytics.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::KinesisAnalytics::Application.CSVMappingParameters": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalytics-application-csvmappingparameters.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json index dbd0a8d9a2138..09fb40024d528 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisAnalyticsV2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::KinesisAnalyticsV2::Application.ApplicationCodeConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-applicationcodeconfiguration.html", @@ -173,13 +173,6 @@ } } }, - "AWS::KinesisAnalyticsV2::Application.CustomArtifactsConfiguration": { - "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-customartifactsconfiguration.html", - "ItemType": "CustomArtifactConfiguration", - "Required": false, - "Type": "List", - "UpdateType": "Mutable" - }, "AWS::KinesisAnalyticsV2::Application.DeployAsApplicationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-deployasapplicationconfiguration.html", "Properties": { @@ -580,8 +573,9 @@ }, "CustomArtifactsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisanalyticsv2-application-zeppelinapplicationconfiguration.html#cfn-kinesisanalyticsv2-application-zeppelinapplicationconfiguration-customartifactsconfiguration", + "ItemType": "CustomArtifactConfiguration", "Required": false, - "Type": "CustomArtifactsConfiguration", + "Type": "List", "UpdateType": "Mutable" }, "DeployAsApplicationConfiguration": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json index 12805dd4b8543..e4db8a913d1fd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisFirehose.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::KinesisFirehose::DeliveryStream.AmazonopensearchserviceBufferingHints": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-kinesisfirehose-deliverystream-amazonopensearchservicebufferinghints.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json new file mode 100644 index 0000000000000..2b6061aa77a15 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_KinesisVideo.json @@ -0,0 +1,90 @@ +{ + "$version": "53.0.0", + "PropertyTypes": {}, + "ResourceTypes": { + "AWS::KinesisVideo::SignalingChannel": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-signalingchannel.html", + "Properties": { + "MessageTtlSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-signalingchannel.html#cfn-kinesisvideo-signalingchannel-messagettlseconds", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-signalingchannel.html#cfn-kinesisvideo-signalingchannel-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-signalingchannel.html#cfn-kinesisvideo-signalingchannel-tags", + "DuplicatesAllowed": true, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Type": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-signalingchannel.html#cfn-kinesisvideo-signalingchannel-type", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::KinesisVideo::Stream": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html", + "Properties": { + "DataRetentionInHours": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-dataretentioninhours", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "DeviceName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-devicename", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "KmsKeyId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-kmskeyid", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "MediaType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-mediatype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Name": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-name", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-kinesisvideo-stream.html#cfn-kinesisvideo-stream-tags", + "DuplicatesAllowed": true, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + } + } +} diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json index 3469bd4537b61..5b1a3090c00dd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LakeFormation.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::LakeFormation::DataLakeSettings.Admins": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lakeformation-datalakesettings-admins.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json index 3f19bf4e27cd4..397ccdb2d5cc8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lambda.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Lambda::Alias.AliasRoutingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-alias-aliasroutingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json index d549b8d0ceea5..3cd46fdcb36e5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lex.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Lex::Bot.BotLocale": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-bot-botlocale.html", @@ -972,14 +972,14 @@ "Properties": { "BotAliasLocaleSetting": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-botalias-botaliaslocalesettingsitem.html#cfn-lex-botalias-botaliaslocalesettingsitem-botaliaslocalesetting", - "Required": false, + "Required": true, "Type": "BotAliasLocaleSettings", "UpdateType": "Mutable" }, "LocaleId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-botalias-botaliaslocalesettingsitem.html#cfn-lex-botalias-botaliaslocalesettingsitem-localeid", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" } } @@ -1077,6 +1077,7 @@ "CloudWatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lex-botalias-textlogdestination.html#cfn-lex-botalias-textlogdestination-cloudwatch", "Required": false, + "Type": "CloudWatchLogGroupLogDestination", "UpdateType": "Mutable" } } diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json index 3237b87d3480f..e856b69991447 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LicenseManager.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::LicenseManager::License.BorrowConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-licensemanager-license-borrowconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json index 902b100affa10..7d62d286225e8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Lightsail.json @@ -1,6 +1,23 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { + "AWS::Lightsail::Bucket.AccessRules": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html", + "Properties": { + "AllowPublicOverrides": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html#cfn-lightsail-bucket-accessrules-allowpublicoverrides", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "GetObject": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-bucket-accessrules.html#cfn-lightsail-bucket-accessrules-getobject", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::Lightsail::Database.RelationalDatabaseParameter": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lightsail-database-relationaldatabaseparameter.html", "Properties": { @@ -328,6 +345,153 @@ } }, "ResourceTypes": { + "AWS::Lightsail::Alarm": { + "Attributes": { + "AlarmArn": { + "PrimitiveType": "String" + }, + "State": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html", + "Properties": { + "AlarmName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-alarmname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "ComparisonOperator": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-comparisonoperator", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ContactProtocols": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-contactprotocols", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "DatapointsToAlarm": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-datapointstoalarm", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, + "EvaluationPeriods": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-evaluationperiods", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Mutable" + }, + "MetricName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-metricname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "MonitoredResourceName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-monitoredresourcename", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "NotificationEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-notificationenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "NotificationTriggers": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-notificationtriggers", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Threshold": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-threshold", + "PrimitiveType": "Double", + "Required": true, + "UpdateType": "Mutable" + }, + "TreatMissingData": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-alarm.html#cfn-lightsail-alarm-treatmissingdata", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, + "AWS::Lightsail::Bucket": { + "Attributes": { + "AbleToUpdateBundle": { + "PrimitiveType": "Boolean" + }, + "BucketArn": { + "PrimitiveType": "String" + }, + "Url": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html", + "Properties": { + "AccessRules": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-accessrules", + "Required": false, + "Type": "AccessRules", + "UpdateType": "Mutable" + }, + "BucketName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-bucketname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "BundleId": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-bundleid", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "ObjectVersioning": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-objectversioning", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "ReadOnlyAccessAccounts": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-readonlyaccessaccounts", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "ResourcesReceivingAccess": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-resourcesreceivingaccess", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-bucket.html#cfn-lightsail-bucket-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::Lightsail::Database": { "Attributes": { "DatabaseArn": { @@ -614,6 +778,113 @@ } } }, + "AWS::Lightsail::LoadBalancer": { + "Attributes": { + "LoadBalancerArn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html", + "Properties": { + "AttachedInstances": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-attachedinstances", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "HealthCheckPath": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-healthcheckpath", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "InstancePort": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-instanceport", + "PrimitiveType": "Integer", + "Required": true, + "UpdateType": "Immutable" + }, + "IpAddressType": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-ipaddresstype", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Immutable" + }, + "LoadBalancerName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-loadbalancername", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "SessionStickinessEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-sessionstickinessenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "SessionStickinessLBCookieDurationSeconds": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-sessionstickinesslbcookiedurationseconds", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Tags": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancer.html#cfn-lightsail-loadbalancer-tags", + "DuplicatesAllowed": false, + "ItemType": "Tag", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::Lightsail::LoadBalancerTlsCertificate": { + "Attributes": { + "LoadBalancerTlsCertificateArn": { + "PrimitiveType": "String" + }, + "Status": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html", + "Properties": { + "CertificateAlternativeNames": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html#cfn-lightsail-loadbalancertlscertificate-certificatealternativenames", + "DuplicatesAllowed": false, + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Immutable" + }, + "CertificateDomainName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html#cfn-lightsail-loadbalancertlscertificate-certificatedomainname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "CertificateName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html#cfn-lightsail-loadbalancertlscertificate-certificatename", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "IsAttached": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html#cfn-lightsail-loadbalancertlscertificate-isattached", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "LoadBalancerName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lightsail-loadbalancertlscertificate.html#cfn-lightsail-loadbalancertlscertificate-loadbalancername", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::Lightsail::StaticIp": { "Attributes": { "IpAddress": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json index 4d767f5282b3d..0ad633b4df290 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Location.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Location::Map.MapConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-location-map-mapconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json index fc07ea9f614f2..8e70fa0cee778 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Logs.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Logs::MetricFilter.MetricTransformation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-logs-metricfilter-metrictransformation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json index 1b7a74838f773..6dfa099a6e479 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutEquipment.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutEquipment::InferenceScheduler": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json index c131262d72c13..67912366eea7e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutMetrics.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::LookoutMetrics::Alert.Action": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lookoutmetrics-alert-action.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json index 7aa7ee90d896e..1c1d4d7d25ca6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_LookoutVision.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::LookoutVision::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json index b59094231d5b1..20185e02691b9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MSK.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MSK::Cluster.BrokerLogs": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-msk-cluster-brokerlogs.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json index a4b0cc2d0cac3..bc2e6d1d9e0ec 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MWAA.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MWAA::Environment.LoggingConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mwaa-environment-loggingconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json index fc77dc43a7452..e944f609e3dcf 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Macie.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Macie::FindingsFilter.Criterion": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-macie-findingsfilter-criterion.html" diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json index 2ea4dacbd3812..7e665fcab8308 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ManagedBlockchain.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ManagedBlockchain::Member.ApprovalThresholdPolicy": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-managedblockchain-member-approvalthresholdpolicy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json index c1011b3822fb8..0b5b342924b9a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConnect.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MediaConnect::Flow.Encryption": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconnect-flow-encryption.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json index 789f20be61802..7d37f987f2243 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaConvert.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MediaConvert::JobTemplate.AccelerationSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediaconvert-jobtemplate-accelerationsettings.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json index d6477927136a7..a9575f7be0518 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaLive.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MediaLive::Channel.AacSettings": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-aacsettings.html", @@ -2498,6 +2498,12 @@ "Required": false, "UpdateType": "Mutable" }, + "ProgramDateTimeClock": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-hlsgroupsettings.html#cfn-medialive-channel-hlsgroupsettings-programdatetimeclock", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, "ProgramDateTimePeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-hlsgroupsettings.html#cfn-medialive-channel-hlsgroupsettings-programdatetimeperiod", "PrimitiveType": "Integer", @@ -2900,6 +2906,12 @@ "Type": "NetworkInputSettings", "UpdateType": "Mutable" }, + "Scte35Pid": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-inputsettings.html#cfn-medialive-channel-inputsettings-scte35pid", + "PrimitiveType": "Integer", + "Required": false, + "UpdateType": "Mutable" + }, "Smpte2038DataPreference": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-medialive-channel-inputsettings.html#cfn-medialive-channel-inputsettings-smpte2038datapreference", "PrimitiveType": "String", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json index 80e444a1ef2ab..9bdd30e498d88 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaPackage.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MediaPackage::Asset.EgressEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediapackage-asset-egressendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json index 4ec158f45b659..a8fedcb4c8ba6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MediaStore.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MediaStore::Container.CorsRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-mediastore-container-corsrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json index 253492dd950ea..6bb085b310c19 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_MemoryDB.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::MemoryDB::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-memorydb-cluster-endpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json index 6e07877a6fa3b..50bc432104720 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Neptune.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Neptune::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-neptune-dbcluster-dbclusterrole.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json index a22f4a66f4e2a..eec6716b217f5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkFirewall.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::NetworkFirewall::Firewall.SubnetMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkfirewall-firewall-subnetmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json index 7e58784a9252e..d45f96e89d874 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NetworkManager.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::NetworkManager::Device.Location": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-networkmanager-device-location.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json index 216c612062463..468c9bd9c0de3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_NimbleStudio.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::NimbleStudio::LaunchProfile.StreamConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html", @@ -23,6 +23,18 @@ "Required": false, "UpdateType": "Mutable" }, + "MaxStoppedSessionLengthInMinutes": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html#cfn-nimblestudio-launchprofile-streamconfiguration-maxstoppedsessionlengthinminutes", + "PrimitiveType": "Double", + "Required": false, + "UpdateType": "Mutable" + }, + "SessionStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html#cfn-nimblestudio-launchprofile-streamconfiguration-sessionstorage", + "Required": false, + "Type": "StreamConfigurationSessionStorage", + "UpdateType": "Mutable" + }, "StreamingImageIds": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfiguration.html#cfn-nimblestudio-launchprofile-streamconfiguration-streamingimageids", "PrimitiveItemType": "String", @@ -32,6 +44,41 @@ } } }, + "AWS::NimbleStudio::LaunchProfile.StreamConfigurationSessionStorage": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfigurationsessionstorage.html", + "Properties": { + "Mode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfigurationsessionstorage.html#cfn-nimblestudio-launchprofile-streamconfigurationsessionstorage-mode", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Root": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamconfigurationsessionstorage.html#cfn-nimblestudio-launchprofile-streamconfigurationsessionstorage-root", + "Required": false, + "Type": "StreamingSessionStorageRoot", + "UpdateType": "Mutable" + } + } + }, + "AWS::NimbleStudio::LaunchProfile.StreamingSessionStorageRoot": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamingsessionstorageroot.html", + "Properties": { + "Linux": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamingsessionstorageroot.html#cfn-nimblestudio-launchprofile-streamingsessionstorageroot-linux", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "Windows": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-launchprofile-streamingsessionstorageroot.html#cfn-nimblestudio-launchprofile-streamingsessionstorageroot-windows", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + } + } + }, "AWS::NimbleStudio::Studio.StudioEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-nimblestudio-studio-studioencryptionconfiguration.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json index f4753b6728cb2..19bc22d9b94c5 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpenSearchService.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::OpenSearchService::Domain.AdvancedSecurityOptionsInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-advancedsecurityoptionsinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json index e9a7d969929e3..519d76d6ef930 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorks.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::OpsWorks::App.DataSource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworks-app-datasource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json index 6407b0a13eff9..570877333c9e0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_OpsWorksCM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::OpsWorksCM::Server.EngineAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opsworkscm-server-engineattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json index f7780de4ffa81..035194219a700 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Panorama.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Panorama::ApplicationInstance.ManifestOverridesPayload": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-panorama-applicationinstance-manifestoverridespayload.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json index f936ef091c57d..bfa0c21284177 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Pinpoint.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Pinpoint::ApplicationSettings.CampaignHook": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpoint-applicationsettings-campaignhook.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json index 289dbb9112f78..32bbb1cb6b4c6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_PinpointEmail.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::PinpointEmail::ConfigurationSet.DeliveryOptions": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-pinpointemail-configurationset-deliveryoptions.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json index 69ee160e8aed9..cc2db7366f3bc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QLDB.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::QLDB::Stream.KinesisConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-qldb-stream-kinesisconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json index 7f6af37a51dd6..5a5bdfa8e6c2a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_QuickSight.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::QuickSight::Analysis.AnalysisError": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-quicksight-analysis-analysiserror.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json index b7abd7455ed14..819cfadbef10c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RAM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::RAM::ResourceShare": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json index be257feaff05a..cd571a339ddde 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RDS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::RDS::DBCluster.DBClusterRole": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-dbcluster-dbclusterrole.html", @@ -913,9 +913,6 @@ }, "Endpoint": { "PrimitiveType": "String" - }, - "VpcId": { - "PrimitiveType": "String" } }, "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbproxy.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json index e27e8b1929418..b983fb62b43a4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RUM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::RUM::AppMonitor.AppMonitorConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rum-appmonitor-appmonitorconfiguration.html", @@ -84,13 +84,13 @@ "Domain": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rum-appmonitor.html#cfn-rum-appmonitor-domain", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Mutable" }, "Name": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rum-appmonitor.html#cfn-rum-appmonitor-name", "PrimitiveType": "String", - "Required": false, + "Required": true, "UpdateType": "Immutable" }, "Tags": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json index 7c30e088626f6..9c5f46ad18b47 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Redshift.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Redshift::Cluster.Endpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-redshift-cluster-endpoint.html", @@ -688,6 +688,7 @@ "PrimitiveType": "String" }, "EventCategoriesList": { + "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Type": "List" }, @@ -712,6 +713,7 @@ }, "EventCategories": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-eventsubscription.html#cfn-redshift-eventsubscription-eventcategories", + "DuplicatesAllowed": false, "PrimitiveItemType": "String", "Required": false, "Type": "List", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json index 27da931caf75f..a40b344e967e8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RefactorSpaces.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::RefactorSpaces::Application.ApiGatewayProxyInput": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-refactorspaces-application-apigatewayproxyinput.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json index 12780b8a4fcf6..c0c686cdd3ffd 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Rekognition.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::Rekognition::Project": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json index 7f57e440f6e3d..604616dca92c4 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResilienceHub.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ResilienceHub::App.PhysicalResourceId": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resiliencehub-app-physicalresourceid.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json index 6b20961efaba9..598676fe5f284 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ResourceGroups.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ResourceGroups::Group.ConfigurationItem": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resourcegroups-group-configurationitem.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json index f1dc11ec946cf..3722ce17511d9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_RoboMaker.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::RoboMaker::RobotApplication.RobotSoftwareSuite": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-robomaker-robotapplication-robotsoftwaresuite.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json index d5962dd8539df..86a247178c9df 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Route53::HealthCheck.HealthCheckTag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-healthcheck-healthchecktag.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json index bfba22f4b7eb2..41460af15abff 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryControl.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Route53RecoveryControl::Cluster.ClusterEndpoint": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoverycontrol-cluster-clusterendpoint.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json index ff940848a67ca..2b3279a4837de 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53RecoveryReadiness.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Route53RecoveryReadiness::ResourceSet.DNSTargetResource": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53recoveryreadiness-resourceset-dnstargetresource.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json index 56a57bba38b8e..5a7beb7b41b77 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Route53Resolver.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Route53Resolver::FirewallRuleGroup.FirewallRule": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53resolver-firewallrulegroup-firewallrule.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json index 13ac2d46ffcca..0de3c71167d87 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::S3::AccessPoint.PublicAccessBlockConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-accesspoint-publicaccessblockconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json index fdbb700a1ce2b..bf370b284d998 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3ObjectLambda.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::S3ObjectLambda::AccessPoint.ObjectLambdaConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3objectlambda-accesspoint-objectlambdaconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json index 9b946aa3347f9..6d51b5629d95f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_S3Outposts.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::S3Outposts::AccessPoint.VpcConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3outposts-accesspoint-vpcconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json index 9644ed554308b..db00243b9966a 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SDB.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SDB::Domain": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json index 397068c73789a..a9d0cb754399f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SES.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SES::ConfigurationSetEventDestination.CloudWatchDestination": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ses-configurationseteventdestination-cloudwatchdestination.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json index 02c7e403852b0..2180ca857d4c3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SNS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SNS::Topic.Subscription": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sns-subscription.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json index 6aab0c995c982..2b450c599cfbe 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SQS.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SQS::Queue": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json index 3d8dd0f30e8cf..0d805d217d26b 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSM.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SSM::Association.InstanceAssociationOutputLocation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-association-instanceassociationoutputlocation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json index 0e21e2dd610ce..900a141fa92a9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMContacts.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SSMContacts::Contact.ChannelTargetInfo": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmcontacts-contact-channeltargetinfo.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json index adb3f2ccd9b5b..ae5f675cd73bb 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSMIncidents.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SSMIncidents::ReplicationSet.RegionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssmincidents-replicationset-regionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json index 393ac6eb62393..4cc7c4cbbbd3d 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SSO.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SSO::InstanceAccessControlAttributeConfiguration.AccessControlAttribute": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sso-instanceaccesscontrolattributeconfiguration-accesscontrolattribute.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json index d403883bf7782..9017b0273ba4e 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecretsManager.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::SecretsManager::RotationSchedule.HostedRotationLambda": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-rotationschedule-hostedrotationlambda.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json index cab99669df416..588dd5b237b85 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_SecurityHub.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::SecurityHub::Hub": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json index 11ceb02c1e8a9..e099af115a6e0 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalog.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ServiceCatalog::CloudFormationProduct.ProvisioningArtifactProperties": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicecatalog-cloudformationproduct-provisioningartifactproperties.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json index dc7b2564fd7dd..04a430b65b113 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceCatalogAppRegistry.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": {}, "ResourceTypes": { "AWS::ServiceCatalogAppRegistry::Application": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json index a7ccbaca17162..fbca8eca4ac59 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_ServiceDiscovery.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::ServiceDiscovery::PrivateDnsNamespace.PrivateDnsPropertiesMutable": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-servicediscovery-privatednsnamespace-privatednspropertiesmutable.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json index 476cea51a1bff..ea9c0b912e504 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Signer.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Signer::SigningProfile.SignatureValidityPeriod": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-signer-signingprofile-signaturevalidityperiod.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json index 7766fb34ff2b1..9383689adb8e6 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_StepFunctions.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::StepFunctions::Activity.TagsEntry": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stepfunctions-activity-tagsentry.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json index e4af4726fc3c7..475928ccf870c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Synthetics.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Synthetics::Canary.ArtifactConfig": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-synthetics-canary-artifactconfig.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json index 85528a70118c0..83f96b43ef29c 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Timestream.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Timestream::ScheduledQuery.DimensionMapping": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-timestream-scheduledquery-dimensionmapping.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json index 1db8b7569e709..b2444f54f903f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Transfer.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Transfer::Server.EndpointDetails": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-endpointdetails.html", @@ -79,6 +79,12 @@ "PrimitiveType": "String", "Required": false, "UpdateType": "Mutable" + }, + "TlsSessionResumptionMode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-transfer-server-protocoldetails.html#cfn-transfer-server-protocoldetails-tlssessionresumptionmode", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" } } }, diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json index 8d37cb0415d5f..cc9564c086725 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAF.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::WAF::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-waf-bytematchset-bytematchtuples.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json index 99b05bc44c1bf..46672ee17706f 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFRegional.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::WAFRegional::ByteMatchSet.ByteMatchTuple": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafregional-bytematchset-bytematchtuple.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json index 182513fb99ac8..92696be1e5e71 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WAFv2.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::WAFv2::LoggingConfiguration.FieldToMatch": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-loggingconfiguration-fieldtomatch.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json index be28ec3aa48cd..41508ba070cb9 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_Wisdom.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::Wisdom::Assistant.ServerSideEncryptionConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wisdom-assistant-serversideencryptionconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json index b0be0061fce3e..e826ef93d5988 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_WorkSpaces.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::WorkSpaces::ConnectionAlias.ConnectionAliasAssociation": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-workspaces-connectionalias-connectionaliasassociation.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json index 47777483c0b07..27d718a9553d3 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_AWS_XRay.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "AWS::XRay::Group.InsightsConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-xray-group-insightsconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json index d16ed81e4dbf4..ffcdf5f553add 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Alexa_ASK.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "Alexa::ASK::Skill.AuthenticationConfiguration": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ask-skill-authenticationconfiguration.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json index 5cfd5af565437..bd2527c9ebc66 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/000_Tag.json @@ -1,5 +1,5 @@ { - "$version": "51.0.0", + "$version": "53.0.0", "PropertyTypes": { "Tag": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-resource-tags.html", diff --git a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json index 376194e28bb48..551a6434fe1f8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json +++ b/packages/@aws-cdk/cfnspec/spec-source/specification/000_cfn/000_official/001_Version.json @@ -1,3 +1,3 @@ { - "ResourceSpecificationVersion": "51.0.0" + "ResourceSpecificationVersion": "53.0.0" } diff --git a/packages/@aws-cdk/cloud-assembly-schema/package.json b/packages/@aws-cdk/cloud-assembly-schema/package.json index 138b2d479483d..10f27bc65691d 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/package.json +++ b/packages/@aws-cdk/cloud-assembly-schema/package.json @@ -67,7 +67,7 @@ "@types/semver": "^7.3.9", "jest": "^27.4.7", "mock-fs": "^4.14.0", - "typescript-json-schema": "^0.52.0" + "typescript-json-schema": "^0.53.0" }, "repository": { "url": "https://github.com/aws/aws-cdk.git", diff --git a/packages/@aws-cdk/cloudformation-diff/package.json b/packages/@aws-cdk/cloudformation-diff/package.json index 3b3bbe8511093..6cbf48e79210d 100644 --- a/packages/@aws-cdk/cloudformation-diff/package.json +++ b/packages/@aws-cdk/cloudformation-diff/package.json @@ -36,7 +36,7 @@ "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", "@types/string-width": "^4.0.1", - "fast-check": "^2.20.0", + "fast-check": "^2.21.0", "jest": "^27.4.7", "ts-jest": "^27.1.2" }, diff --git a/packages/@aws-cdk/cloudformation-include/package.json b/packages/@aws-cdk/cloudformation-include/package.json index b7ecf1786b1f1..425756e78a3c7 100644 --- a/packages/@aws-cdk/cloudformation-include/package.json +++ b/packages/@aws-cdk/cloudformation-include/package.json @@ -150,6 +150,7 @@ "@aws-cdk/aws-finspace": "0.0.0", "@aws-cdk/aws-fis": "0.0.0", "@aws-cdk/aws-fms": "0.0.0", + "@aws-cdk/aws-forecast": "0.0.0", "@aws-cdk/aws-frauddetector": "0.0.0", "@aws-cdk/aws-fsx": "0.0.0", "@aws-cdk/aws-gamelift": "0.0.0", @@ -163,6 +164,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", + "@aws-cdk/aws-inspectorv2": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", "@aws-cdk/aws-iotanalytics": "0.0.0", @@ -176,7 +178,9 @@ "@aws-cdk/aws-kendra": "0.0.0", "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kinesisanalytics": "0.0.0", + "@aws-cdk/aws-kinesisanalyticsv2": "0.0.0", "@aws-cdk/aws-kinesisfirehose": "0.0.0", + "@aws-cdk/aws-kinesisvideo": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lakeformation": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", @@ -334,6 +338,7 @@ "@aws-cdk/aws-finspace": "0.0.0", "@aws-cdk/aws-fis": "0.0.0", "@aws-cdk/aws-fms": "0.0.0", + "@aws-cdk/aws-forecast": "0.0.0", "@aws-cdk/aws-frauddetector": "0.0.0", "@aws-cdk/aws-fsx": "0.0.0", "@aws-cdk/aws-gamelift": "0.0.0", @@ -347,6 +352,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", + "@aws-cdk/aws-inspectorv2": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", "@aws-cdk/aws-iotanalytics": "0.0.0", @@ -360,7 +366,9 @@ "@aws-cdk/aws-kendra": "0.0.0", "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kinesisanalytics": "0.0.0", + "@aws-cdk/aws-kinesisanalyticsv2": "0.0.0", "@aws-cdk/aws-kinesisfirehose": "0.0.0", + "@aws-cdk/aws-kinesisvideo": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lakeformation": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", diff --git a/packages/@aws-cdk/core/package.json b/packages/@aws-cdk/core/package.json index 1773f8e806d33..5889ed8517559 100644 --- a/packages/@aws-cdk/core/package.json +++ b/packages/@aws-cdk/core/package.json @@ -185,7 +185,7 @@ "@types/minimatch": "^3.0.5", "@types/node": "^10.17.60", "@types/sinon": "^9.0.11", - "fast-check": "^2.20.0", + "fast-check": "^2.21.0", "jest": "^27.4.7", "lodash": "^4.17.21", "sinon": "^9.2.4", diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 6f7474a1486cf..cb6707b8b1611 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -79,7 +79,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/aws-events": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@aws-cdk/aws-ssm": "0.0.0", @@ -94,7 +94,7 @@ "aws-sdk": "^2.848.0", "aws-sdk-mock": "^5.5.1", "fs-extra": "^9.1.0", - "nock": "^13.2.1", + "nock": "^13.2.2", "sinon": "^9.2.4" }, "dependencies": { diff --git a/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource.test.ts b/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource.test.ts index f072c0f926875..c3df398f6f5dd 100644 --- a/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource.test.ts +++ b/packages/@aws-cdk/custom-resources/test/aws-custom-resource/aws-custom-resource.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import * as iam from '@aws-cdk/aws-iam'; import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; @@ -33,7 +33,7 @@ test('aws sdk js custom resource with onCreate and onDelete', () => { }); // THEN - expect(stack).toHaveResource('Custom::LogRetentionPolicy', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetentionPolicy', { 'Create': JSON.stringify({ 'service': 'CloudWatchLogs', 'action': 'putRetentionPolicy', @@ -55,7 +55,7 @@ test('aws sdk js custom resource with onCreate and onDelete', () => { 'InstallLatestAwsSdk': true, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { 'PolicyDocument': { 'Statement': [ { @@ -95,7 +95,7 @@ test('onCreate defaults to onUpdate', () => { }); // THEN - expect(stack).toHaveResource('Custom::S3PutObject', { + Template.fromStack(stack).hasResourceProperties('Custom::S3PutObject', { 'Create': JSON.stringify({ 'service': 's3', 'action': 'putObject', @@ -148,7 +148,7 @@ test('with custom policyStatements', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { 'PolicyDocument': { 'Statement': [ { @@ -207,7 +207,7 @@ test('booleans are encoded in the stringified parameters object', () => { }); // THEN - expect(stack).toHaveResource('Custom::ServiceAction', { + Template.fromStack(stack).hasResourceProperties('Custom::ServiceAction', { 'Create': JSON.stringify({ 'service': 'service', 'action': 'action', @@ -263,7 +263,7 @@ test('encodes physical resource id reference', () => { }); // THEN - expect(stack).toHaveResource('Custom::ServiceAction', { + Template.fromStack(stack).hasResourceProperties('Custom::ServiceAction', { 'Create': JSON.stringify({ 'service': 'service', 'action': 'action', @@ -296,7 +296,7 @@ test('timeout defaults to 2 minutes', () => { }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Timeout: 120, }); }); @@ -317,7 +317,7 @@ test('can specify timeout', () => { }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Timeout: 900, }); }); @@ -340,7 +340,7 @@ test('implements IGrantable', () => { // WHEN role.grantPassRole(customResource.grantPrincipal); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -376,11 +376,11 @@ test('can use existing role', () => { }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: 'arn:aws:iam::123456789012:role/CoolRole', }); - expect(stack).not.toHaveResource('AWS::IAM::Role'); + Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 0); }); test('getData', () => { @@ -524,7 +524,7 @@ test('getDataString', () => { }); // THEN - expect(stack).toHaveResource('Custom::AWS', { + Template.fromStack(stack).hasResourceProperties('Custom::AWS', { Create: { 'Fn::Join': [ '', @@ -559,7 +559,7 @@ test('can specify log retention', () => { }); // THEN - expect(stack).toHaveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: { 'Fn::Join': [ '', @@ -591,7 +591,7 @@ test('disable AWS SDK installation', () => { }); // THEN - expect(stack).toHaveResource('Custom::AWS', { + Template.fromStack(stack).hasResourceProperties('Custom::AWS', { 'InstallLatestAwsSdk': false, }); }); @@ -612,7 +612,7 @@ test('can specify function name', () => { }); // THEN - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { FunctionName: 'my-cool-function', }); }); @@ -640,7 +640,7 @@ test('separate policies per custom resource', () => { }); // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -652,7 +652,7 @@ test('separate policies per custom resource', () => { Version: '2012-10-17', }, }); - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -690,7 +690,7 @@ test('tokens can be used as dictionary keys', () => { }); // THEN - expect(stack).toHaveResource('Custom::AWS', { + Template.fromStack(stack).hasResourceProperties('Custom::AWS', { Create: { 'Fn::Join': [ '', @@ -730,7 +730,7 @@ test('assumedRoleArn adds statement for sts:assumeRole', () => { // THEN - expect(stack).toHaveResource('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { diff --git a/packages/@aws-cdk/custom-resources/test/provider-framework/provider.test.ts b/packages/@aws-cdk/custom-resources/test/provider-framework/provider.test.ts index 724c76425a1ee..ac09be73e0f89 100644 --- a/packages/@aws-cdk/custom-resources/test/provider-framework/provider.test.ts +++ b/packages/@aws-cdk/custom-resources/test/provider-framework/provider.test.ts @@ -1,4 +1,5 @@ import * as path from 'path'; +import { Template } from '@aws-cdk/assertions'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; @@ -7,8 +8,6 @@ import { Duration, Stack } from '@aws-cdk/core'; import * as cr from '../../lib'; import * as util from '../../lib/provider-framework/util'; -import '@aws-cdk/assert-internal/jest'; - test('security groups are applied to all framework functions', () => { // GIVEN @@ -34,7 +33,7 @@ test('security groups are applied to all framework functions', () => { securityGroups: [securityGroup], }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onEvent', VpcConfig: { SecurityGroupIds: [ @@ -48,7 +47,7 @@ test('security groups are applied to all framework functions', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.isComplete', VpcConfig: { SecurityGroupIds: [ @@ -62,7 +61,7 @@ test('security groups are applied to all framework functions', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onTimeout', VpcConfig: { SecurityGroupIds: [ @@ -101,7 +100,7 @@ test('vpc is applied to all framework functions', () => { vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onEvent', VpcConfig: { SubnetIds: [ @@ -111,7 +110,7 @@ test('vpc is applied to all framework functions', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.isComplete', VpcConfig: { SubnetIds: [ @@ -121,7 +120,7 @@ test('vpc is applied to all framework functions', () => { }, }); - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onTimeout', VpcConfig: { SubnetIds: [ @@ -149,23 +148,23 @@ test('minimal setup', () => { // THEN // framework "onEvent" handler - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onEvent', Environment: { Variables: { USER_ON_EVENT_FUNCTION_ARN: { 'Fn::GetAtt': ['MyHandler6B74D312', 'Arn'] } } }, Timeout: 900, }); // user "onEvent" handler - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'index.onEvent', }); // no framework "is complete" handler or state machine - expect(stack).not.toHaveResource('AWS::StepFunctions::StateMachine'); - expect(stack).not.toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).resourceCountIs('AWS::StepFunctions::StateMachine', 0); + expect(Template.fromStack(stack).findResources('AWS::Lambda::Function', { Handler: 'framework.isComplete', Timeout: 900, - }); + })).toEqual({}); }); test('if isComplete is specified, the isComplete framework handler is also included', () => { @@ -193,7 +192,7 @@ test('if isComplete is specified, the isComplete framework handler is also inclu }, }; - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onEvent', Timeout: 900, Environment: { @@ -204,19 +203,19 @@ test('if isComplete is specified, the isComplete framework handler is also inclu }, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.isComplete', Timeout: 900, Environment: expectedEnv, }); - expect(stack).toHaveResource('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Handler: 'framework.onTimeout', Timeout: 900, Environment: expectedEnv, }); - expect(stack).toHaveResource('AWS::StepFunctions::StateMachine', { + Template.fromStack(stack).hasResourceProperties('AWS::StepFunctions::StateMachine', { DefinitionString: { 'Fn::Join': [ '', @@ -310,7 +309,7 @@ describe('log retention', () => { }); // THEN - expect(stack).toHaveResource('Custom::LogRetention', { + Template.fromStack(stack).hasResourceProperties('Custom::LogRetention', { LogGroupName: { 'Fn::Join': [ '', @@ -340,7 +339,7 @@ describe('log retention', () => { }); // THEN - expect(stack).not.toHaveResource('Custom::LogRetention'); + Template.fromStack(stack).resourceCountIs('Custom::LogRetention', 0); }); }); @@ -363,7 +362,7 @@ describe('role', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'MyRoleF48FFE04', @@ -387,7 +386,7 @@ describe('role', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { Role: { 'Fn::GetAtt': [ 'MyProviderframeworkonEventServiceRole8761E48D', @@ -415,7 +414,7 @@ describe('name', () => { }); // THEN - expect(stack).toHaveResourceLike('AWS::Lambda::Function', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', { FunctionName: providerFunctionName, }); }); diff --git a/packages/@aws-cdk/custom-resources/test/provider-framework/waiter-state-machine.test.ts b/packages/@aws-cdk/custom-resources/test/provider-framework/waiter-state-machine.test.ts index f9b683417dc94..7548f4e151041 100644 --- a/packages/@aws-cdk/custom-resources/test/provider-framework/waiter-state-machine.test.ts +++ b/packages/@aws-cdk/custom-resources/test/provider-framework/waiter-state-machine.test.ts @@ -1,4 +1,4 @@ -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; import { Code, Function as lambdaFn, Runtime } from '@aws-cdk/aws-lambda'; import { Duration, Stack } from '@aws-cdk/core'; import { Node } from 'constructs'; @@ -35,7 +35,7 @@ describe('state machine', () => { // THEN const roleId = 'statemachineRole52044F93'; - expect(stack).toHaveResourceLike('AWS::StepFunctions::StateMachine', { + Template.fromStack(stack).hasResourceProperties('AWS::StepFunctions::StateMachine', { DefinitionString: { 'Fn::Join': [ '', @@ -54,7 +54,7 @@ describe('state machine', () => { 'Fn::GetAtt': [roleId, 'Arn'], }, }); - expect(stack).toHaveResourceLike('AWS::IAM::Role', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { @@ -77,7 +77,7 @@ describe('state machine', () => { Version: '2012-10-17', }, }); - expect(stack).toHaveResourceLike('AWS::IAM::Policy', { + Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { diff --git a/packages/@aws-cdk/cx-api/lib/features.ts b/packages/@aws-cdk/cx-api/lib/features.ts index 74f4ff63082a6..f4ced76f60d3a 100644 --- a/packages/@aws-cdk/cx-api/lib/features.ts +++ b/packages/@aws-cdk/cx-api/lib/features.ts @@ -170,6 +170,25 @@ export const CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021 = '@aws-cdk/aws-cl */ export const TARGET_PARTITIONS = '@aws-cdk/core:target-partitions'; +/** + * Enable this feature flag to configure default logging behavior for the ECS Service Extensions. This will enable the + * `awslogs` log driver for the application container of the service to send the container logs to CloudWatch Logs. + * + * This is a feature flag as the new behavior provides a better default experience for the users. + */ +export const ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER = '@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver'; + +/** + * Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names. + * + * Previously, the generated Launch Template names were only unique within a stack because they were based only on the + * `Instance` construct ID. If another stack that has an `Instance` with the same construct ID is deployed in the same + * account and region, the deployments would always fail as the generated Launch Template names were the same. + * + * The new implementation addresses this issue by generating the Launch Template name with the `Names.uniqueId` method. + */ +export const EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME = '@aws-cdk/aws-ec2:uniqueImdsv2TemplateName'; + /** * This map includes context keys and values for feature flags that enable * capabilities "from the future", which we could not introduce as the default @@ -197,6 +216,8 @@ export const FUTURE_FLAGS: { [key: string]: boolean } = { [EFS_DEFAULT_ENCRYPTION_AT_REST]: true, [LAMBDA_RECOGNIZE_VERSION_PROPS]: true, [CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021]: true, + [ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER]: true, + [EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME]: true, // We will advertise this flag when the feature is complete // [NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: 'true', @@ -235,6 +256,8 @@ const FUTURE_FLAGS_DEFAULTS: { [key: string]: boolean } = { [EFS_DEFAULT_ENCRYPTION_AT_REST]: false, [LAMBDA_RECOGNIZE_VERSION_PROPS]: false, [CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021]: false, + [ECS_SERVICE_EXTENSIONS_ENABLE_DEFAULT_LOG_DRIVER]: false, + [EC2_UNIQUE_IMDSV2_LAUNCH_TEMPLATE_NAME]: false, }; export function futureFlagDefault(flag: string): boolean | undefined { diff --git a/packages/@aws-cdk/lambda-layer-awscli/package.json b/packages/@aws-cdk/lambda-layer-awscli/package.json index 759a1c35ec1d9..cf5a3d857f5b3 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/package.json +++ b/packages/@aws-cdk/lambda-layer-awscli/package.json @@ -73,7 +73,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cdk-integ-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", diff --git a/packages/@aws-cdk/lambda-layer-awscli/test/awscli-layer.test.ts b/packages/@aws-cdk/lambda-layer-awscli/test/awscli-layer.test.ts index 2a5c4b7d80043..561bb87a14ac7 100644 --- a/packages/@aws-cdk/lambda-layer-awscli/test/awscli-layer.test.ts +++ b/packages/@aws-cdk/lambda-layer-awscli/test/awscli-layer.test.ts @@ -1,6 +1,6 @@ import { Stack } from '@aws-cdk/core'; import { AwsCliLayer } from '../lib'; -import '@aws-cdk/assert-internal/jest'; +import { Template } from '@aws-cdk/assertions'; test('synthesized to a layer version', () => { //GIVEN @@ -10,7 +10,7 @@ test('synthesized to a layer version', () => { new AwsCliLayer(stack, 'MyLayer'); // THEN - expect(stack).toHaveResource('AWS::Lambda::LayerVersion', { + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::LayerVersion', { Description: '/opt/awscli/aws', }); }); diff --git a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts index 67dd7c2f35cc4..0beae3ea56fa1 100644 --- a/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/codepipeline/codepipeline.ts @@ -12,6 +12,7 @@ import { DockerCredential, dockerCredentialsInstallCommands, DockerCredentialUsa import { GraphNodeCollection, isGraph, AGraphNode, PipelineGraph } from '../helpers-internal'; import { PipelineBase } from '../main'; import { AssetSingletonRole } from '../private/asset-singleton-role'; +import { preferredCliVersion } from '../private/cli-version'; import { appOf, assemblyBuilderOf, embeddedAsmPath, obtainScope } from '../private/construct-internals'; import { toPosixPath } from '../private/fs'; import { actionName, stackVariableNamespace } from '../private/identifiers'; @@ -303,6 +304,7 @@ export class CodePipeline extends PipelineBase { private _cloudAssemblyFileSet?: FileSet; private readonly singlePublisherPerAssetType: boolean; + private readonly cliVersion?: string; constructor(scope: Construct, id: string, private readonly props: CodePipelineProps) { super(scope, id, props); @@ -310,6 +312,7 @@ export class CodePipeline extends PipelineBase { this.selfMutation = props.selfMutation ?? true; this.dockerCredentials = props.dockerCredentials ?? []; this.singlePublisherPerAssetType = !(props.publishAssetsInParallel ?? true); + this.cliVersion = props.cliVersion ?? preferredCliVersion(); } /** @@ -603,7 +606,7 @@ export class CodePipeline extends PipelineBase { } private selfMutateAction(): ICodePipelineActionFactory { - const installSuffix = this.props.cliVersion ? `@${this.props.cliVersion}` : ''; + const installSuffix = this.cliVersion ? `@${this.cliVersion}` : ''; const pipelineStack = Stack.of(this.pipeline); const pipelineStackIdentifier = pipelineStack.node.path ?? pipelineStack.stackName; @@ -649,7 +652,7 @@ export class CodePipeline extends PipelineBase { } private publishAssetsAction(node: AGraphNode, assets: StackAsset[]): ICodePipelineActionFactory { - const installSuffix = this.props.cliVersion ? `@${this.props.cliVersion}` : ''; + const installSuffix = this.cliVersion ? `@${this.cliVersion}` : ''; const commands = assets.map(asset => { const relativeAssetManifestPath = path.relative(this.myCxAsmRoot, asset.assetManifestPath); diff --git a/packages/@aws-cdk/pipelines/lib/helpers-internal/graph.ts b/packages/@aws-cdk/pipelines/lib/helpers-internal/graph.ts index 6b1c2d85ee701..798cc207f0aeb 100644 --- a/packages/@aws-cdk/pipelines/lib/helpers-internal/graph.ts +++ b/packages/@aws-cdk/pipelines/lib/helpers-internal/graph.ts @@ -35,7 +35,7 @@ export class GraphNode { */ public get allDeps(): GraphNode[] { const fromParent = this.parentGraph?.allDeps ?? []; - return [...this.dependencies, ...fromParent]; + return Array.from(new Set([...this.dependencies, ...fromParent])); } public dependOn(...dependencies: Array | undefined>) { @@ -382,4 +382,4 @@ function projectDependencies(dependencies: Map, Set export function isGraph(x: GraphNode): x is Graph { return x instanceof Graph; -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts index ef0d1d209619b..e7490778420b5 100644 --- a/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts +++ b/packages/@aws-cdk/pipelines/lib/legacy/pipeline.ts @@ -9,6 +9,7 @@ import { AssetType } from '../blueprint/asset-type'; import { dockerCredentialsInstallCommands, DockerCredential, DockerCredentialUsage } from '../docker-credentials'; import { ApplicationSecurityCheck } from '../private/application-security-check'; import { AssetSingletonRole } from '../private/asset-singleton-role'; +import { preferredCliVersion } from '../private/cli-version'; import { appOf, assemblyBuilderOf } from '../private/construct-internals'; import { DeployCdkStackAction, PublishAssetsAction, UpdatePipelineAction } from './actions'; import { AddStageOptions, AssetPublishingCommand, BaseStageOptions, CdkStage, StackOutput } from './stage'; @@ -219,9 +220,11 @@ export class CdkPipeline extends CoreConstruct { private readonly _cloudAssemblyArtifact: codepipeline.Artifact; private readonly _dockerCredentials: DockerCredential[]; private _applicationSecurityCheck?: ApplicationSecurityCheck; + private readonly cliVersion?: string; constructor(scope: Construct, id: string, props: CdkPipelineProps) { super(scope, id); + this.cliVersion = props.cdkCliVersion ?? preferredCliVersion(); if (!App.isApp(this.node.root)) { throw new Error('CdkPipeline must be created under an App'); @@ -287,7 +290,7 @@ export class CdkPipeline extends CoreConstruct { actions: [new UpdatePipelineAction(this, 'UpdatePipeline', { cloudAssemblyInput: this._cloudAssemblyArtifact, pipelineStackHierarchicalId: pipelineStack.node.path, - cdkCliVersion: props.cdkCliVersion, + cdkCliVersion: this.cliVersion, projectName: maybeSuffix(props.pipelineName, '-selfupdate'), privileged: props.supportDockerAssets, dockerCredentials: this._dockerCredentials, @@ -298,7 +301,7 @@ export class CdkPipeline extends CoreConstruct { this._assets = new AssetPublishing(this, 'Assets', { cloudAssemblyInput: this._cloudAssemblyArtifact, - cdkCliVersion: props.cdkCliVersion, + cdkCliVersion: this.cliVersion, pipeline: this._pipeline, projectName: maybeSuffix(props.pipelineName, '-publish'), vpc: props.vpc, diff --git a/packages/@aws-cdk/pipelines/lib/private/cli-version.ts b/packages/@aws-cdk/pipelines/lib/private/cli-version.ts new file mode 100644 index 0000000000000..07ef8fa384fb3 --- /dev/null +++ b/packages/@aws-cdk/pipelines/lib/private/cli-version.ts @@ -0,0 +1,41 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * Return the preferred CLI version for the current CDK Library version + * + * This is necessary to prevent cxapi version incompatibility between the two + * CDK major versions. Since changes currently go into v1 before they go into + * v2, a cxapi change can be released in v1 while the v2 CLI doesn't support it + * yet. + * + * In those cases, simply installing the "latest" CLI (2) is not good enough + * because it won't be able to read the Cloud Assembly of the v1 app. + * + * Find this version by finding the containing `package.json` and reading + * `preferredCdkCliVersion` from it. + */ +export function preferredCliVersion(): string | undefined { + const pjLocation = findUp('package.json', __dirname); + if (!pjLocation) { + return undefined; + } + const pj = JSON.parse(fs.readFileSync(pjLocation, { encoding: 'utf-8' })); + return pj.preferredCdkCliVersion ? `${pj.preferredCdkCliVersion}` : undefined; +} + +export function findUp(name: string, directory: string): string | undefined { + const absoluteDirectory = path.resolve(directory); + + const file = path.join(directory, name); + if (fs.existsSync(file)) { + return file; + } + + const { root } = path.parse(absoluteDirectory); + if (absoluteDirectory == root) { + return undefined; + } + + return findUp(name, path.dirname(absoluteDirectory)); +} \ No newline at end of file diff --git a/packages/@aws-cdk/pipelines/package.json b/packages/@aws-cdk/pipelines/package.json index 27227f1760150..1249fa706977b 100644 --- a/packages/@aws-cdk/pipelines/package.json +++ b/packages/@aws-cdk/pipelines/package.json @@ -156,5 +156,6 @@ "homepage": "https://github.com/aws/aws-cdk", "publishConfig": { "tag": "latest" - } + }, + "preferredCdkCliVersion": "1" } diff --git a/packages/@aws-cdk/pipelines/test/blueprint/helpers-internal/dependencies.test.ts b/packages/@aws-cdk/pipelines/test/blueprint/helpers-internal/dependencies.test.ts index f577ffae4f80c..9610472554301 100644 --- a/packages/@aws-cdk/pipelines/test/blueprint/helpers-internal/dependencies.test.ts +++ b/packages/@aws-cdk/pipelines/test/blueprint/helpers-internal/dependencies.test.ts @@ -50,3 +50,22 @@ describe('with nested graphs', () => { ]); }); }); + +test('duplicate dependencies are ignored', () => { + mkGraph('G', G => { + const A = G.graph('A', [], GA => { + GA.node('aa'); + }); + + // parent graph depnds on A also + const B = G.graph('B', [A], GB => { + // duplicate dependency on A + GB.graph('BB', [A], GBB => { + GBB.node('bbb'); + }); + GB.node('bb'); + }); + + expect(nodeNames(B.tryGetChild('BB')!.allDeps)).toStrictEqual(['A']); + }); +}); diff --git a/packages/@aws-cdk/pipelines/test/compliance/assets.test.ts b/packages/@aws-cdk/pipelines/test/compliance/assets.test.ts index e4bb58afc47f5..2828d494c1c3b 100644 --- a/packages/@aws-cdk/pipelines/test/compliance/assets.test.ts +++ b/packages/@aws-cdk/pipelines/test/compliance/assets.test.ts @@ -599,7 +599,7 @@ behavior('can supply pre-install scripts to asset upload', (suite) => { BuildSpec: Match.serializedJson(Match.objectLike({ phases: { install: { - commands: ['npm config set registry https://registry.com', 'npm install -g cdk-assets'], + commands: ['npm config set registry https://registry.com', 'npm install -g cdk-assets@1'], }, }, })), diff --git a/packages/@aws-cdk/pipelines/test/compliance/self-mutation.test.ts b/packages/@aws-cdk/pipelines/test/compliance/self-mutation.test.ts index f672898107c30..ca552d56f1332 100644 --- a/packages/@aws-cdk/pipelines/test/compliance/self-mutation.test.ts +++ b/packages/@aws-cdk/pipelines/test/compliance/self-mutation.test.ts @@ -52,7 +52,7 @@ behavior('CodePipeline has self-mutation stage', (suite) => { BuildSpec: Match.serializedJson(Match.objectLike({ phases: { install: { - commands: ['npm install -g aws-cdk'], + commands: ['npm install -g aws-cdk@1'], }, build: { commands: Match.arrayWith(['cdk -a . deploy PipelineStack --require-approval=never --verbose']), @@ -288,7 +288,7 @@ behavior('self-mutation stage can be customized with BuildSpec', (suite) => { BuildSpec: Match.serializedJson(Match.objectLike({ phases: { install: { - commands: ['npm config set registry example.com', 'npm install -g aws-cdk'], + commands: ['npm config set registry example.com', 'npm install -g aws-cdk@1'], }, build: { commands: Match.arrayWith(['cdk -a . deploy PipelineStack --require-approval=never --verbose']), diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json index 0ea92e8bd1fe0..c0d89b2bf135a 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline-with-vpc.expected.json @@ -858,7 +858,7 @@ "ProjectName": { "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" }, - "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"9eda7f97d24aac861052bb47a41b80eecdd56096bf9a88a27c88d94c463785c8\"}]" + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"c0779bd925c3a7f19be75a4973c668d10d00ce3552b882c7d2ba3fa3cee6d976\"}]" }, "InputArtifacts": [ { @@ -1936,7 +1936,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { @@ -2278,7 +2278,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-Beta/PipelineStackBetaStack1E6541489.assets.json\\\" --verbose publish \\\"8289faf53c7da377bb2b90615999171adef5e1d8f6b88810e5fef75e6ca09ba5:current_account-current_region\\\"\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-Beta/PipelineStackBetaStack1E6541489.assets.json\\\" --verbose publish \\\"8289faf53c7da377bb2b90615999171adef5e1d8f6b88810e5fef75e6ca09ba5:current_account-current_region\\\"\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { @@ -2379,7 +2379,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-Beta/PipelineStackBetaStack1E6541489.assets.json\\\" --verbose publish \\\"ac76997971c3f6ddf37120660003f1ced72b4fc58c498dfd99c78fa77e721e0e:current_account-current_region\\\"\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-Beta/PipelineStackBetaStack1E6541489.assets.json\\\" --verbose publish \\\"ac76997971c3f6ddf37120660003f1ced72b4fc58c498dfd99c78fa77e721e0e:current_account-current_region\\\"\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { diff --git a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json index c73962569d56f..6e12dae20df4d 100644 --- a/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.newpipeline.expected.json @@ -324,7 +324,7 @@ "ProjectName": { "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" }, - "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"9eda7f97d24aac861052bb47a41b80eecdd56096bf9a88a27c88d94c463785c8\"}]" + "EnvironmentVariables": "[{\"name\":\"_PROJECT_CONFIG_HASH\",\"type\":\"PLAINTEXT\",\"value\":\"c0779bd925c3a7f19be75a4973c668d10d00ce3552b882c7d2ba3fa3cee6d976\"}]" }, "InputArtifacts": [ { @@ -2329,7 +2329,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json index f7be2a6cc06e5..64471fdf6b4c8 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets-single-upload.expected.json @@ -413,7 +413,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -444,7 +445,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineAssetsFileAsset5D8C5DA6" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -1364,7 +1366,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json index 4137af5b8b0c6..01eafcfb30eef 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline-with-assets.expected.json @@ -413,7 +413,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -444,7 +445,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineAssetsFileAsset185A67CB4" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -470,7 +472,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineAssetsFileAsset24D2D639B" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -1390,7 +1393,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { @@ -1578,7 +1581,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-PreProd/PipelineStackPreProdStack65A0AD1F.assets.json\\\" --verbose publish \\\"8289faf53c7da377bb2b90615999171adef5e1d8f6b88810e5fef75e6ca09ba5:12345678-test-region\\\"\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-PreProd/PipelineStackPreProdStack65A0AD1F.assets.json\\\" --verbose publish \\\"8289faf53c7da377bb2b90615999171adef5e1d8f6b88810e5fef75e6ca09ba5:12345678-test-region\\\"\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { @@ -1612,7 +1615,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-PreProd/PipelineStackPreProdStack65A0AD1F.assets.json\\\" --verbose publish \\\"ac76997971c3f6ddf37120660003f1ced72b4fc58c498dfd99c78fa77e721e0e:12345678-test-region\\\"\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g cdk-assets@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk-assets --path \\\"assembly-PipelineStack-PreProd/PipelineStackPreProdStack65A0AD1F.assets.json\\\" --verbose publish \\\"ac76997971c3f6ddf37120660003f1ced72b4fc58c498dfd99c78fa77e721e0e:12345678-test-region\\\"\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { diff --git a/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json b/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json index 8f2e83582be38..90d937525afc8 100644 --- a/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json +++ b/packages/@aws-cdk/pipelines/test/integ.pipeline.expected.json @@ -403,7 +403,8 @@ "Configuration": { "ProjectName": { "Ref": "PipelineUpdatePipelineSelfMutationDAA41400" - } + }, + "EnvironmentVariables": "[{\"name\":\"CDK_CLI_VERSION\",\"type\":\"PLAINTEXT\",\"value\":\"1\"}]" }, "InputArtifacts": [ { @@ -1323,7 +1324,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"install\": {\n \"commands\": [\n \"npm install -g aws-cdk@1\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"cdk -a . deploy PipelineStack --require-approval=never --verbose\"\n ]\n }\n }\n}", "Type": "CODEPIPELINE" }, "Cache": { diff --git a/packages/@aws-cdk/yaml-cfn/package.json b/packages/@aws-cdk/yaml-cfn/package.json index cbe41433d2ac7..b0035c4e80552 100644 --- a/packages/@aws-cdk/yaml-cfn/package.json +++ b/packages/@aws-cdk/yaml-cfn/package.json @@ -69,7 +69,7 @@ "yaml": "1.10.2" }, "devDependencies": { - "@aws-cdk/assert-internal": "0.0.0", + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.4.0", diff --git a/packages/@aws-cdk/yaml-cfn/test/deserialization.test.ts b/packages/@aws-cdk/yaml-cfn/test/deserialization.test.ts index 3d790ea9d60e6..3c6bbc09f2397 100644 --- a/packages/@aws-cdk/yaml-cfn/test/deserialization.test.ts +++ b/packages/@aws-cdk/yaml-cfn/test/deserialization.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import * as yaml_cfn from '../lib'; test('Unquoted year-month-day is treated as a string, not a Date', () => { diff --git a/packages/@aws-cdk/yaml-cfn/test/serialization.test.ts b/packages/@aws-cdk/yaml-cfn/test/serialization.test.ts index 3237f16f986b4..7b9d07ca2a50d 100644 --- a/packages/@aws-cdk/yaml-cfn/test/serialization.test.ts +++ b/packages/@aws-cdk/yaml-cfn/test/serialization.test.ts @@ -1,4 +1,3 @@ -import '@aws-cdk/assert-internal/jest'; import * as yaml_cfn from '../lib'; test('An object with a single string value is serialized as a simple string', () => { diff --git a/packages/aws-cdk-lib/package.json b/packages/aws-cdk-lib/package.json index 28ae2cab5d2b4..e55df0ea2542c 100644 --- a/packages/aws-cdk-lib/package.json +++ b/packages/aws-cdk-lib/package.json @@ -171,6 +171,7 @@ "@aws-cdk/aws-codestarconnections": "0.0.0", "@aws-cdk/aws-codestarnotifications": "0.0.0", "@aws-cdk/aws-cognito": "0.0.0", + "@aws-cdk/aws-cognito-identitypool": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", @@ -210,6 +211,7 @@ "@aws-cdk/aws-finspace": "0.0.0", "@aws-cdk/aws-fis": "0.0.0", "@aws-cdk/aws-fms": "0.0.0", + "@aws-cdk/aws-forecast": "0.0.0", "@aws-cdk/aws-frauddetector": "0.0.0", "@aws-cdk/aws-fsx": "0.0.0", "@aws-cdk/aws-gamelift": "0.0.0", @@ -224,6 +226,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", + "@aws-cdk/aws-inspectorv2": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", @@ -239,8 +242,10 @@ "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kinesisanalytics": "0.0.0", "@aws-cdk/aws-kinesisanalytics-flink": "0.0.0", + "@aws-cdk/aws-kinesisanalyticsv2": "0.0.0", "@aws-cdk/aws-kinesisfirehose": "0.0.0", "@aws-cdk/aws-kinesisfirehose-destinations": "0.0.0", + "@aws-cdk/aws-kinesisvideo": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lakeformation": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", @@ -346,7 +351,7 @@ "@types/fs-extra": "^8.1.2", "@types/node": "^10.17.60", "constructs": "^3.3.69", - "esbuild": "^0.14.10", + "esbuild": "^0.14.11", "fs-extra": "^9.1.0", "ts-node": "^9.1.1", "typescript": "~3.8.3" @@ -428,6 +433,7 @@ "./aws-codestarconnections": "./aws-codestarconnections/index.js", "./aws-codestarnotifications": "./aws-codestarnotifications/index.js", "./aws-cognito": "./aws-cognito/index.js", + "./aws-cognito-identitypool": "./aws-cognito-identitypool/index.js", "./aws-config": "./aws-config/index.js", "./aws-connect": "./aws-connect/index.js", "./aws-cur": "./aws-cur/index.js", @@ -594,5 +600,6 @@ "./pipelines/.warnings.jsii.js": "./pipelines/.warnings.jsii.js", "./pipelines/lib/helpers-internal": "./pipelines/lib/helpers-internal/index.js", "./region-info": "./region-info/index.js" - } + }, + "preferredCdkCliVersion": "2" } diff --git a/packages/aws-cdk/README.md b/packages/aws-cdk/README.md index 0afbb913fa0e0..f1c63975641ac 100644 --- a/packages/aws-cdk/README.md +++ b/packages/aws-cdk/README.md @@ -362,7 +362,7 @@ and that you have the necessary IAM permissions to update the resources that are Hotswapping is currently supported for the following changes (additional changes will be supported in the future): -- Code asset and tag changes of AWS Lambda functions. +- Code asset (including Docker image and inline code) and tag changes of AWS Lambda functions. - AWS Lambda Versions and Aliases changes. - Definition changes of AWS Step Functions State Machines. - Container asset changes of AWS ECS Services. @@ -436,6 +436,13 @@ for example: Note that `watch` by default uses hotswap deployments (see above for details) -- to turn them off, pass the `--no-hotswap` option when invoking it. +By default `watch` will also monitor all CloudWatch Log Groups in your application and stream the log events +locally to your terminal. To disable this feature you can pass the `--no-logs` option when invoking it: + +```console +$ cdk watch --no-logs +``` + **Note**: This command is considered experimental, and might have breaking changes in the future. diff --git a/packages/aws-cdk/bin/cdk.ts b/packages/aws-cdk/bin/cdk.ts index bcb536815ae6b..5b82a72eab5d2 100644 --- a/packages/aws-cdk/bin/cdk.ts +++ b/packages/aws-cdk/bin/cdk.ts @@ -124,6 +124,13 @@ async function parseCommandLineArguments() { desc: 'Continuously observe the project files, ' + 'and deploy the given stack(s) automatically when changes are detected. ' + 'Implies --hotswap by default', + }) + .options('logs', { + type: 'boolean', + default: true, + desc: 'Show CloudWatch log events from all resources in the selected Stacks in the terminal. ' + + "'true' by default, use --no-logs to turn off. " + + "Only in effect if specified alongside the '--watch' option", }), ) .command('watch [STACKS..]', "Shortcut for 'deploy --watch'", yargs => yargs @@ -157,6 +164,12 @@ async function parseCommandLineArguments() { 'which skips CloudFormation and updates the resources directly, ' + 'and falls back to a full deployment if that is not possible. ' + "'true' by default, use --no-hotswap to turn off", + }) + .options('logs', { + type: 'boolean', + default: true, + desc: 'Show CloudWatch log events from all resources in the selected Stacks in the terminal. ' + + "'true' by default, use --no-logs to turn off", }), ) .command('destroy [STACKS..]', 'Destroy the stack(s) named STACKS', yargs => yargs @@ -376,6 +389,7 @@ async function initCommandLine() { rollback: configuration.settings.get(['rollback']), hotswap: args.hotswap, watch: args.watch, + traceLogs: args.logs, }); case 'watch': @@ -395,6 +409,7 @@ async function initCommandLine() { progress: configuration.settings.get(['progress']), rollback: configuration.settings.get(['rollback']), hotswap: args.hotswap, + traceLogs: args.logs, }); case 'destroy': diff --git a/packages/aws-cdk/lib/api/aws-auth/sdk.ts b/packages/aws-cdk/lib/api/aws-auth/sdk.ts index c45098277fbf1..b805597cc010b 100644 --- a/packages/aws-cdk/lib/api/aws-auth/sdk.ts +++ b/packages/aws-cdk/lib/api/aws-auth/sdk.ts @@ -62,6 +62,7 @@ export interface ISDK { kms(): AWS.KMS; stepFunctions(): AWS.StepFunctions; codeBuild(): AWS.CodeBuild + cloudWatchLogs(): AWS.CloudWatchLogs; } /** @@ -185,6 +186,10 @@ export class SDK implements ISDK { return this.wrapServiceErrorHandling(new AWS.CodeBuild(this.config)); } + public cloudWatchLogs(): AWS.CloudWatchLogs { + return this.wrapServiceErrorHandling(new AWS.CloudWatchLogs(this.config)); + } + public async currentAccount(): Promise { // Get/refresh if necessary before we can access `accessKeyId` await this.forceCredentialRetrieval(); diff --git a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts index 8cece9d8eed30..df20bf0f62b63 100644 --- a/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts +++ b/packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import * as cxschema from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; +import * as logging from '../../logging'; import { Mode, SdkProvider, ISDK } from '../aws-auth'; import { deployStack, DeployStackResult } from '../deploy-stack'; import { DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo } from '../toolkit-info'; @@ -65,7 +66,18 @@ export class BootstrapStack { const newVersion = bootstrapVersionFromTemplate(template); if (this.currentToolkitInfo.found && newVersion < this.currentToolkitInfo.version && !options.force) { - throw new Error(`Not downgrading existing bootstrap stack from version '${this.currentToolkitInfo.version}' to version '${newVersion}'. Use --force to force or set the '@aws-cdk/core:newStyleStackSynthesis' feature flag in cdk.json to use the latest bootstrap version.`); + 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 { + noOp: true, + outputs: {}, + stackArn: this.currentToolkitInfo.bootstrapStack.stackId, + }; } const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap')); diff --git a/packages/aws-cdk/lib/api/cloudformation-deployments.ts b/packages/aws-cdk/lib/api/cloudformation-deployments.ts index c461c5ac24dc5..a4438ff0ca8f7 100644 --- a/packages/aws-cdk/lib/api/cloudformation-deployments.ts +++ b/packages/aws-cdk/lib/api/cloudformation-deployments.ts @@ -27,6 +27,92 @@ export async function replaceEnvPlaceholders(object: A, env: cxap }); } +/** + * SDK obtained by assuming the lookup role + * for a given environment + */ +export interface PreparedSdkWithLookupRoleForEnvironment { + /** + * The SDK for the given environment + */ + readonly sdk: ISDK; + + /** + * The resolved environment for the stack + * (no more 'unknown-account/unknown-region') + */ + readonly resolvedEnvironment: cxapi.Environment; + + /** + * Whether or not the assume role was successful. + * If the assume role was not successful (false) + * then that means that the 'sdk' returned contains + * the default credentials (not the assume role credentials) + */ + readonly didAssumeRole: boolean; +} + +/** + * Try to use the bootstrap lookupRole. There are two scenarios that are handled here + * 1. The lookup role may not exist (it was added in bootstrap stack version 7) + * 2. The lookup role may not have the correct permissions (ReadOnlyAccess was added in + * bootstrap stack version 8) + * + * In the case of 1 (lookup role doesn't exist) `forEnvironment` will either: + * 1. Return the default credentials if the default credentials are for the stack account + * 2. Throw an error if the default credentials are not for the stack account. + * + * If we successfully assume the lookup role we then proceed to 2 and check whether the bootstrap + * stack version is valid. If it is not we throw an error which should be handled in the calling + * function (and fallback to use a different role, etc) + * + * If we do not successfully assume the lookup role, but do get back the default credentials + * then return those and note that we are returning the default credentials. The calling + * function can then decide to use them or fallback to another role. + */ +export async function prepareSdkWithLookupRoleFor( + sdkProvider: SdkProvider, + stack: cxapi.CloudFormationStackArtifact, +): Promise { + const resolvedEnvironment = await sdkProvider.resolveEnvironment(stack.environment); + + // Substitute any placeholders with information about the current environment + const arns = await replaceEnvPlaceholders({ + lookupRoleArn: stack.lookupRole?.arn, + }, resolvedEnvironment, sdkProvider); + + // try to assume the lookup role + const warningMessage = `Could not assume ${arns.lookupRoleArn}, proceeding anyway.`; + const upgradeMessage = `(To get rid of this warning, please upgrade to bootstrap version >= ${stack.lookupRole?.requiresBootstrapStackVersion})`; + try { + const stackSdk = await sdkProvider.forEnvironment(resolvedEnvironment, Mode.ForReading, { + assumeRoleArn: arns.lookupRoleArn, + assumeRoleExternalId: stack.lookupRole?.assumeRoleExternalId, + }); + + // if we succeed in assuming the lookup role, make sure we have the correct bootstrap stack version + if (stackSdk.didAssumeRole && stack.lookupRole?.bootstrapStackVersionSsmParameter && stack.lookupRole.requiresBootstrapStackVersion) { + const version = await ToolkitInfo.versionFromSsmParameter(stackSdk.sdk, stack.lookupRole.bootstrapStackVersionSsmParameter); + if (version < stack.lookupRole.requiresBootstrapStackVersion) { + throw new Error(`Bootstrap stack version '${stack.lookupRole.requiresBootstrapStackVersion}' is required, found version '${version}'.`); + } + // we may not have assumed the lookup role because one was not provided + // if that is the case then don't print the upgrade warning + } else if (!stackSdk.didAssumeRole && stack.lookupRole?.requiresBootstrapStackVersion) { + warning(upgradeMessage); + } + return { ...stackSdk, resolvedEnvironment }; + } catch (e) { + debug(e); + // only print out the warnings if the lookupRole exists AND there is a required + // bootstrap version, otherwise the warnings will print `undefined` + if (stack.lookupRole && stack.lookupRole.requiresBootstrapStackVersion) { + warning(warningMessage); + warning(upgradeMessage); + } + throw (e); + } +} export interface DeployStackOptions { /** @@ -171,31 +257,6 @@ export interface ProvisionerProps { sdkProvider: SdkProvider; } -/** - * SDK obtained by assuming the lookup role - * for a given environment - */ -export interface PreparedSdkWithLookupRoleForEnvironment { - /** - * The SDK for the given environment - */ - readonly sdk: ISDK; - - /** - * The resolved environment for the stack - * (no more 'unknown-account/unknown-region') - */ - readonly resolvedEnvironment: cxapi.Environment; - - /** - * Whether or not the assume role was successful. - * If the assume role was not successful (false) - * then that means that the 'sdk' returned contains - * the default credentials (not the assume role credentials) - */ - readonly didAssumeRole: boolean; -} - /** * SDK obtained by assuming the deploy role * for a given environment @@ -237,7 +298,7 @@ export class CloudFormationDeployments { let stackSdk: ISDK | undefined = undefined; // try to assume the lookup role and fallback to the deploy role try { - const result = await this.prepareSdkWithLookupRoleFor(stackArtifact); + const result = await prepareSdkWithLookupRoleFor(this.sdkProvider, stackArtifact); if (result.didAssumeRole) { stackSdk = result.sdk; } @@ -311,59 +372,6 @@ export class CloudFormationDeployments { return stack.exists; } - /** - * Try to use the bootstrap lookupRole. There are two scenarios that are handled here - * 1. The lookup role may not exist (it was added in bootstrap stack version 7) - * 2. The lookup role may not have the correct permissions (ReadOnlyAccess was added in - * bootstrap stack version 8) - * - * In the case of 1 (lookup role doesn't exist) `forEnvironment` will either: - * 1. Return the default credentials if the default credentials are for the stack account - * 2. Throw an error if the default credentials are not for the stack account. - * - * If we successfully assume the lookup role we then proceed to 2 and check whether the bootstrap - * stack version is valid. If it is not we throw an error which should be handled in the calling - * function (and fallback to use a different role, etc) - * - * If we do not successfully assume the lookup role, but do get back the default credentials - * then return those and note that we are returning the default credentials. The calling - * function can then decide to use them or fallback to another role. - */ - private async prepareSdkWithLookupRoleFor(stack: cxapi.CloudFormationStackArtifact): Promise { - const resolvedEnvironment = await this.sdkProvider.resolveEnvironment(stack.environment); - - // Substitute any placeholders with information about the current environment - const arns = await replaceEnvPlaceholders({ - lookupRoleArn: stack.lookupRole?.arn, - }, resolvedEnvironment, this.sdkProvider); - - // try to assume the lookup role - const warningMessage = `Could not assume ${arns.lookupRoleArn}, proceeding anyway.`; - const upgradeMessage = `(To get rid of this warning, please upgrade to bootstrap version >= ${stack.lookupRole?.requiresBootstrapStackVersion})`; - try { - const stackSdk = await this.sdkProvider.forEnvironment(resolvedEnvironment, Mode.ForReading, { - assumeRoleArn: arns.lookupRoleArn, - assumeRoleExternalId: stack.lookupRole?.assumeRoleExternalId, - }); - - // if we succeed in assuming the lookup role, make sure we have the correct bootstrap stack version - if (stackSdk.didAssumeRole && stack.lookupRole?.bootstrapStackVersionSsmParameter && stack.lookupRole.requiresBootstrapStackVersion) { - const version = await ToolkitInfo.versionFromSsmParameter(stackSdk.sdk, stack.lookupRole.bootstrapStackVersionSsmParameter); - if (version < stack.lookupRole.requiresBootstrapStackVersion) { - throw new Error(`Bootstrap stack version '${stack.lookupRole.requiresBootstrapStackVersion}' is required, found version '${version}'.`); - } - } else if (!stackSdk.didAssumeRole) { - warning(upgradeMessage); - } - return { ...stackSdk, resolvedEnvironment }; - } catch (e) { - debug(e); - warning(warningMessage); - warning(upgradeMessage); - throw (e); - } - } - /** * Get the environment necessary for touching the given stack * diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index 6cb665b115e9f..76b9386cc9550 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -9,9 +9,9 @@ import { AssetManifestBuilder } from '../util/asset-manifest-builder'; import { publishAssets } from '../util/asset-publishing'; import { contentHash } from '../util/content-hash'; import { ISDK, SdkProvider } from './aws-auth'; +import { CfnEvaluationException } from './evaluate-cloudformation-template'; import { tryHotswapDeployment } from './hotswap-deployments'; import { ICON } from './hotswap/common'; -import { CfnEvaluationException } from './hotswap/evaluate-cloudformation-template'; import { ToolkitInfo } from './toolkit-info'; import { changeSetHasNoChanges, CloudFormationStack, TemplateParameters, waitForChangeSet, @@ -28,7 +28,6 @@ export interface DeployStackResult { readonly noOp: boolean; readonly outputs: { [name: string]: string }; readonly stackArn: string; - readonly stackArtifact: cxapi.CloudFormationStackArtifact; } export interface DeployStackOptions { @@ -241,7 +240,6 @@ export async function deployStack(options: DeployStackOptions): Promise; +} + +export class LazyListStackResources implements ListStackResources { + private stackResources: AWS.CloudFormation.StackResourceSummary[] | undefined; + + constructor(private readonly sdk: ISDK, private readonly stackName: string) { + } + + public async listStackResources(): Promise { + if (this.stackResources === undefined) { + this.stackResources = await this.getStackResources(); + } + return this.stackResources; + } + + private async getStackResources(): Promise { + const ret = new Array(); + let nextToken: string | undefined; + do { + const stackResourcesResponse = await this.sdk.cloudFormation().listStackResources({ + StackName: this.stackName, + NextToken: nextToken, + }).promise(); + ret.push(...(stackResourcesResponse.StackResourceSummaries ?? [])); + nextToken = stackResourcesResponse.NextToken; + } while (nextToken); + return ret; + } +} export class CfnEvaluationException extends Error {} @@ -45,6 +77,21 @@ export class EvaluateCloudFormationTemplate { this.urlSuffix = props.urlSuffix; } + public async establishResourcePhysicalName(logicalId: string, physicalNameInCfnTemplate: any): Promise { + if (physicalNameInCfnTemplate != null) { + try { + return await this.evaluateCfnExpression(physicalNameInCfnTemplate); + } catch (e) { + // If we can't evaluate the resource's name CloudFormation expression, + // just look it up in the currently deployed Stack + if (!(e instanceof CfnEvaluationException)) { + throw e; + } + } + } + return this.findPhysicalNameFor(logicalId); + } + public async findPhysicalNameFor(logicalId: string): Promise { const stackResources = await this.stackResources.listStackResources(); return stackResources.find(sr => sr.LogicalResourceId === logicalId)?.PhysicalResourceId; diff --git a/packages/aws-cdk/lib/api/hotswap-deployments.ts b/packages/aws-cdk/lib/api/hotswap-deployments.ts index 2b00ace13c041..da46369aa79c9 100644 --- a/packages/aws-cdk/lib/api/hotswap-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap-deployments.ts @@ -1,14 +1,13 @@ import * as cfn_diff from '@aws-cdk/cloudformation-diff'; import * as cxapi from '@aws-cdk/cx-api'; -import { CloudFormation } from 'aws-sdk'; import * as chalk from 'chalk'; import { print } from '../logging'; import { ISDK, Mode, SdkProvider } from './aws-auth'; import { DeployStackResult } from './deploy-stack'; +import { EvaluateCloudFormationTemplate, LazyListStackResources } from './evaluate-cloudformation-template'; import { isHotswappableCodeBuildProjectChange } from './hotswap/code-build-projects'; -import { ICON, ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate, ListStackResources } from './hotswap/common'; +import { ICON, ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate } from './hotswap/common'; import { isHotswappableEcsServiceChange } from './hotswap/ecs-services'; -import { EvaluateCloudFormationTemplate } from './hotswap/evaluate-cloudformation-template'; import { isHotswappableLambdaFunctionChange } from './hotswap/lambda-functions'; import { isHotswappableS3BucketDeploymentChange } from './hotswap/s3-bucket-deployments'; import { isHotswappableStateMachineChange } from './hotswap/stepfunctions-state-machines'; @@ -40,7 +39,7 @@ export async function tryHotswapDeployment( account: resolvedEnv.account, region: resolvedEnv.region, partition: (await sdk.currentAccount()).partition, - urlSuffix: sdk.getEndpointSuffix, + urlSuffix: (region) => sdk.getEndpointSuffix(region), listStackResources, }); @@ -55,7 +54,7 @@ export async function tryHotswapDeployment( // apply the short-circuitable changes await applyAllHotswappableChanges(sdk, hotswappableChanges); - return { noOp: hotswappableChanges.length === 0, stackArn: cloudFormationStack.stackId, outputs: cloudFormationStack.outputs, stackArtifact }; + return { noOp: hotswappableChanges.length === 0, stackArn: cloudFormationStack.stackId, outputs: cloudFormationStack.outputs }; } async function findAllHotswappableChanges( @@ -211,9 +210,7 @@ function isCandidateForHotswapping(change: cfn_diff.ResourceDifference): Hotswap }; } -async function applyAllHotswappableChanges( - sdk: ISDK, hotswappableChanges: HotswapOperation[], -): Promise { +async function applyAllHotswappableChanges(sdk: ISDK, hotswappableChanges: HotswapOperation[]): Promise { print(`\n${ICON} hotswapping resources:`); return Promise.all(hotswappableChanges.map(hotswapOperation => { return applyHotswappableChange(sdk, hotswapOperation); @@ -238,30 +235,3 @@ async function applyHotswappableChange(sdk: ISDK, hotswapOperation: HotswapOpera } } -class LazyListStackResources implements ListStackResources { - private stackResources: CloudFormation.StackResourceSummary[] | undefined; - - constructor(private readonly sdk: ISDK, private readonly stackName: string) { - } - - async listStackResources(): Promise { - if (this.stackResources === undefined) { - this.stackResources = await this.getStackResources(); - } - return this.stackResources; - } - - private async getStackResources(): Promise { - const ret = new Array(); - let nextToken: string | undefined; - do { - const stackResourcesResponse = await this.sdk.cloudFormation().listStackResources({ - StackName: this.stackName, - NextToken: nextToken, - }).promise(); - ret.push(...(stackResourcesResponse.StackResourceSummaries ?? [])); - nextToken = stackResourcesResponse.NextToken; - } while (nextToken); - return ret; - } -} diff --git a/packages/aws-cdk/lib/api/hotswap/code-build-projects.ts b/packages/aws-cdk/lib/api/hotswap/code-build-projects.ts index 1afdd8acf9fdc..55270d29f8ceb 100644 --- a/packages/aws-cdk/lib/api/hotswap/code-build-projects.ts +++ b/packages/aws-cdk/lib/api/hotswap/code-build-projects.ts @@ -1,7 +1,7 @@ import * as AWS from 'aws-sdk'; import { ISDK } from '../aws-auth'; -import { ChangeHotswapImpact, ChangeHotswapResult, establishResourcePhysicalName, HotswapOperation, HotswappableChangeCandidate, lowerCaseFirstCharacter, transformObjectKeys } from './common'; -import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; +import { EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; +import { ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate, lowerCaseFirstCharacter, transformObjectKeys } from './common'; export async function isHotswappableCodeBuildProjectChange( logicalId: string, change: HotswappableChangeCandidate, evaluateCfnTemplate: EvaluateCloudFormationTemplate, @@ -36,7 +36,7 @@ export async function isHotswappableCodeBuildProjectChange( } } - const projectName = await establishResourcePhysicalName(logicalId, change.newValue.Properties?.Name, evaluateCfnTemplate); + const projectName = await evaluateCfnTemplate.establishResourcePhysicalName(logicalId, change.newValue.Properties?.Name); if (!projectName) { return ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT; } diff --git a/packages/aws-cdk/lib/api/hotswap/common.ts b/packages/aws-cdk/lib/api/hotswap/common.ts index 479a08ebd3986..1a06a8934c6ee 100644 --- a/packages/aws-cdk/lib/api/hotswap/common.ts +++ b/packages/aws-cdk/lib/api/hotswap/common.ts @@ -1,12 +1,7 @@ import * as cfn_diff from '@aws-cdk/cloudformation-diff'; -import { CloudFormation } from 'aws-sdk'; import { ISDK } from '../aws-auth'; -import { CfnEvaluationException, EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; export const ICON = '✨'; -export interface ListStackResources { - listStackResources(): Promise; -} /** * An interface that represents a change that can be deployed in a short-circuit manner. @@ -66,23 +61,6 @@ export class HotswappableChangeCandidate { } } -export async function establishResourcePhysicalName( - logicalId: string, physicalNameInCfnTemplate: any, evaluateCfnTemplate: EvaluateCloudFormationTemplate, -): Promise { - if (physicalNameInCfnTemplate != null) { - try { - return await evaluateCfnTemplate.evaluateCfnExpression(physicalNameInCfnTemplate); - } catch (e) { - // If we can't evaluate the resource's name CloudFormation expression, - // just look it up in the currently deployed Stack - if (!(e instanceof CfnEvaluationException)) { - throw e; - } - } - } - return evaluateCfnTemplate.findPhysicalNameFor(logicalId); -} - /** * This function transforms all keys (recursively) in the provided `val` object. * diff --git a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts index fa9257876467b..1794457d86c9f 100644 --- a/packages/aws-cdk/lib/api/hotswap/ecs-services.ts +++ b/packages/aws-cdk/lib/api/hotswap/ecs-services.ts @@ -1,7 +1,7 @@ import * as AWS from 'aws-sdk'; import { ISDK } from '../aws-auth'; -import { ChangeHotswapImpact, ChangeHotswapResult, establishResourcePhysicalName, HotswapOperation, HotswappableChangeCandidate, lowerCaseFirstCharacter, transformObjectKeys } from './common'; -import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; +import { EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; +import { ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate, lowerCaseFirstCharacter, transformObjectKeys } from './common'; export async function isHotswappableEcsServiceChange( logicalId: string, change: HotswappableChangeCandidate, evaluateCfnTemplate: EvaluateCloudFormationTemplate, @@ -45,7 +45,7 @@ export async function isHotswappableEcsServiceChange( const taskDefinitionResource = change.newValue.Properties; // first, let's get the name of the family - const familyNameOrArn = await establishResourcePhysicalName(logicalId, taskDefinitionResource?.Family, evaluateCfnTemplate); + const familyNameOrArn = await evaluateCfnTemplate.establishResourcePhysicalName(logicalId, taskDefinitionResource?.Family); if (!familyNameOrArn) { // if the Family property has not bee provided, and we can't find it in the current Stack, // this means hotswapping is not possible diff --git a/packages/aws-cdk/lib/api/hotswap/lambda-functions.ts b/packages/aws-cdk/lib/api/hotswap/lambda-functions.ts index d158d5a4ba4de..d2966e756b69d 100644 --- a/packages/aws-cdk/lib/api/hotswap/lambda-functions.ts +++ b/packages/aws-cdk/lib/api/hotswap/lambda-functions.ts @@ -1,7 +1,9 @@ +import { Writable } from 'stream'; +import * as archiver from 'archiver'; import { flatMap } from '../../util'; import { ISDK } from '../aws-auth'; -import { ChangeHotswapImpact, ChangeHotswapResult, establishResourcePhysicalName, HotswapOperation, HotswappableChangeCandidate } from './common'; -import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; +import { CfnEvaluationException, EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; +import { ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate } from './common'; /** * Returns `ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT` if the change cannot be short-circuited, @@ -30,7 +32,7 @@ export async function isHotswappableLambdaFunctionChange( return lambdaCodeChange; } - const functionName = await establishResourcePhysicalName(logicalId, change.newValue.Properties?.FunctionName, evaluateCfnTemplate); + const functionName = await evaluateCfnTemplate.establishResourcePhysicalName(logicalId, change.newValue.Properties?.FunctionName); if (!functionName) { return ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT; } @@ -108,7 +110,7 @@ async function isLambdaFunctionCodeOnlyChange( switch (updatedPropName) { case 'Code': let foundCodeDifference = false; - let s3Bucket = '', s3Key = ''; + let s3Bucket, s3Key, imageUri, functionCodeZip; for (const newPropName in updatedProp.newValue) { switch (newPropName) { @@ -120,6 +122,22 @@ async function isLambdaFunctionCodeOnlyChange( foundCodeDifference = true; s3Key = await evaluateCfnTemplate.evaluateCfnExpression(updatedProp.newValue[newPropName]); break; + case 'ImageUri': + foundCodeDifference = true; + imageUri = await evaluateCfnTemplate.evaluateCfnExpression(updatedProp.newValue[newPropName]); + break; + case 'ZipFile': + foundCodeDifference = true; + // We must create a zip package containing a file with the inline code + const functionCode = await evaluateCfnTemplate.evaluateCfnExpression(updatedProp.newValue[newPropName]); + const functionRuntime = await evaluateCfnTemplate.evaluateCfnExpression(change.newValue.Properties?.Runtime); + if (!functionRuntime) { + return ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT; + } + // file extension must be chosen depending on the runtime + const codeFileExt = determineCodeFileExtFromRuntime(functionRuntime); + functionCodeZip = await zipString(`index.${codeFileExt}`, functionCode); + break; default: return ChangeHotswapImpact.REQUIRES_FULL_DEPLOYMENT; } @@ -128,6 +146,8 @@ async function isLambdaFunctionCodeOnlyChange( code = { s3Bucket, s3Key, + imageUri, + functionCodeZip, }; } break; @@ -165,8 +185,10 @@ interface CfnDiffTagValue { } interface LambdaFunctionCode { - readonly s3Bucket: string; - readonly s3Key: string; + readonly s3Bucket?: string; + readonly s3Key?: string; + readonly imageUri?: string; + readonly functionCodeZip?: Buffer; } enum TagDeletion { @@ -214,6 +236,8 @@ class LambdaFunctionHotswapOperation implements HotswapOperation { FunctionName: this.lambdaFunctionResource.physicalName, S3Bucket: resource.code.s3Bucket, S3Key: resource.code.s3Key, + ImageUri: resource.code.imageUri, + ZipFile: resource.code.functionCodeZip, }).promise(); // only if the code changed is there any point in publishing a new Version @@ -281,3 +305,55 @@ class LambdaFunctionHotswapOperation implements HotswapOperation { return Promise.all(operations); } } + +/** + * Compress a string as a file, returning a promise for the zip buffer + * https://github.com/archiverjs/node-archiver/issues/342 + */ +function zipString(fileName: string, rawString: string): Promise { + return new Promise((resolve, reject) => { + const buffers: Buffer[] = []; + + const converter = new Writable(); + + converter._write = (chunk: Buffer, _: string, callback: () => void) => { + buffers.push(chunk); + process.nextTick(callback); + }; + + converter.on('finish', () => { + resolve(Buffer.concat(buffers)); + }); + + const archive = archiver('zip'); + + archive.on('error', (err) => { + reject(err); + }); + + archive.pipe(converter); + + archive.append(rawString, { + name: fileName, + date: new Date('1980-01-01T00:00:00.000Z'), // Add date to make resulting zip file deterministic + }); + + void archive.finalize(); + }); +} + +/** + * Get file extension from Lambda runtime string. + * We use this extension to create a deployment package from Lambda inline code. + */ +function determineCodeFileExtFromRuntime(runtime: string): string { + if (runtime.startsWith('node')) { + return 'js'; + } + if (runtime.startsWith('python')) { + return 'py'; + } + // Currently inline code only supports Node.js and Python, ignoring other runtimes. + // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html#aws-properties-lambda-function-code-properties + throw new CfnEvaluationException(`runtime ${runtime} is unsupported, only node.js and python runtimes are currently supported.`); +} diff --git a/packages/aws-cdk/lib/api/hotswap/s3-bucket-deployments.ts b/packages/aws-cdk/lib/api/hotswap/s3-bucket-deployments.ts index 5f45d10cfc1f4..7eebe6d0a9437 100644 --- a/packages/aws-cdk/lib/api/hotswap/s3-bucket-deployments.ts +++ b/packages/aws-cdk/lib/api/hotswap/s3-bucket-deployments.ts @@ -1,6 +1,6 @@ import { ISDK } from '../aws-auth'; +import { EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; import { ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate } from './common'; -import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; /** * This means that the value is required to exist by CloudFormation's API (or our S3 Bucket Deployment Lambda) diff --git a/packages/aws-cdk/lib/api/hotswap/stepfunctions-state-machines.ts b/packages/aws-cdk/lib/api/hotswap/stepfunctions-state-machines.ts index 31f5174ea514d..9f746395e9114 100644 --- a/packages/aws-cdk/lib/api/hotswap/stepfunctions-state-machines.ts +++ b/packages/aws-cdk/lib/api/hotswap/stepfunctions-state-machines.ts @@ -1,6 +1,6 @@ import { ISDK } from '../aws-auth'; +import { EvaluateCloudFormationTemplate } from '../evaluate-cloudformation-template'; import { ChangeHotswapImpact, ChangeHotswapResult, HotswapOperation, HotswappableChangeCandidate } from './common'; -import { EvaluateCloudFormationTemplate } from './evaluate-cloudformation-template'; export async function isHotswappableStateMachineChange( logicalId: string, change: HotswappableChangeCandidate, evaluateCfnTemplate: EvaluateCloudFormationTemplate, diff --git a/packages/aws-cdk/lib/api/logs/find-cloudwatch-logs.ts b/packages/aws-cdk/lib/api/logs/find-cloudwatch-logs.ts new file mode 100644 index 0000000000000..1eb775151b322 --- /dev/null +++ b/packages/aws-cdk/lib/api/logs/find-cloudwatch-logs.ts @@ -0,0 +1,120 @@ +import * as cxapi from '@aws-cdk/cx-api'; +import { CloudFormation } from 'aws-sdk'; +import { Mode, SdkProvider, ISDK } from '../aws-auth'; +import { prepareSdkWithLookupRoleFor } from '../cloudformation-deployments'; +import { EvaluateCloudFormationTemplate, LazyListStackResources } from '../evaluate-cloudformation-template'; + +// resource types that have associated CloudWatch Log Groups that should _not_ be monitored +const IGNORE_LOGS_RESOURCE_TYPES = ['AWS::EC2::FlowLog', 'AWS::CloudTrail::Trail', 'AWS::CodeBuild::Project']; + +// Resource types that will create a CloudWatch log group with a specific name if one is not provided. +// The keys are CFN resource types, and the values are the name of the physical name property of that resource +// and the service name that is used in the automatically created CloudWatch log group. +const RESOURCE_TYPES_WITH_IMPLICIT_LOGS: { [cfnResourceType: string]: { [key: string]: string } } = { + 'AWS::Lambda::Function': { + PhysicalNamePropertyName: 'FunctionName', + LogGroupServiceName: 'lambda', + }, +}; + +/** + * Configuration needed to monitor CloudWatch Log Groups + * found in a given CloudFormation Stack + */ +export interface FoundLogGroupsResult { + /** + * The resolved environment (account/region) that the log + * groups are deployed in + */ + readonly env: cxapi.Environment; + + /** + * The SDK that can be used to read events from the CloudWatch + * Log Groups in the given environment + */ + readonly sdk: ISDK; + + /** + * The names of the relevant CloudWatch Log Groups + * in the given CloudFormation template + */ + readonly logGroupNames: string[] +} + +export async function findCloudWatchLogGroups( + sdkProvider: SdkProvider, + stackArtifact: cxapi.CloudFormationStackArtifact, +): Promise { + let sdk: ISDK; + const resolvedEnv = await sdkProvider.resolveEnvironment(stackArtifact.environment); + // try to assume the lookup role and fallback to the default credentials + try { + sdk = (await prepareSdkWithLookupRoleFor(sdkProvider, stackArtifact)).sdk; + } catch (e) { + sdk = (await sdkProvider.forEnvironment(resolvedEnv, Mode.ForReading)).sdk; + } + + const listStackResources = new LazyListStackResources(sdk, stackArtifact.stackName); + const evaluateCfnTemplate = new EvaluateCloudFormationTemplate({ + stackArtifact, + parameters: {}, + account: resolvedEnv.account, + region: resolvedEnv.region, + partition: (await sdk.currentAccount()).partition, + urlSuffix: (region) => sdk.getEndpointSuffix(region), + listStackResources, + }); + + const stackResources = await listStackResources.listStackResources(); + const logGroupNames = findAllLogGroupNames(stackResources, evaluateCfnTemplate); + + return { + env: resolvedEnv, + sdk, + logGroupNames, + }; +} + +/** + * Determine if a CloudWatch Log Group is associated + * with an ignored resource + */ +function isReferencedFromIgnoredResource( + logGroupResource: CloudFormation.StackResourceSummary, + evaluateCfnTemplate: EvaluateCloudFormationTemplate, +): boolean { + let foundReference = false; + const resourcesReferencingLogGroup = evaluateCfnTemplate.findReferencesTo(logGroupResource.LogicalResourceId); + for (const reference of resourcesReferencingLogGroup) { + if (IGNORE_LOGS_RESOURCE_TYPES.includes(reference.Type)) { + foundReference = true; + } + } + return foundReference; +} + +/** + * Find all CloudWatch Log Groups in the deployed template. + * This will find both explicitely created Log Groups (excluding those associated with ignored resources) + * as well as Log Groups created implicitely (i.e. Lambda Functions) + */ +function findAllLogGroupNames( + stackResources: CloudFormation.StackResourceSummary[], + evaluateCfnTemplate: EvaluateCloudFormationTemplate, +): string[] { + return stackResources.reduce((logGroupNames: string[], resource) => { + let logGroupName; + if (resource.ResourceType === 'AWS::Logs::LogGroup') { + if (!isReferencedFromIgnoredResource(resource, evaluateCfnTemplate)) { + logGroupName = resource.PhysicalResourceId; + } + } else if (RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType]) { + const servicePart = RESOURCE_TYPES_WITH_IMPLICIT_LOGS[resource.ResourceType].LogGroupServiceName; + logGroupName = `/aws/${servicePart}/${resource.PhysicalResourceId}`; + } + if (logGroupName) { + logGroupNames.push(logGroupName); + } + return logGroupNames; + }, []); +} diff --git a/packages/aws-cdk/lib/api/logs/logs-monitor.ts b/packages/aws-cdk/lib/api/logs/logs-monitor.ts new file mode 100644 index 0000000000000..f6f2086bc20bf --- /dev/null +++ b/packages/aws-cdk/lib/api/logs/logs-monitor.ts @@ -0,0 +1,223 @@ +import * as util from 'util'; +import * as cxapi from '@aws-cdk/cx-api'; +import * as chalk from 'chalk'; +import { print, error } from '../../logging'; +import { flatten } from '../../util/arrays'; +import { ISDK } from '../aws-auth'; + +/** + * After reading events from all CloudWatch log groups + * how long should we wait to read more events. + * + * If there is some error with reading events (i.e. Throttle) + * then this is also how long we wait until we try again + */ +const SLEEP = 2_000; + +/** + * Represents a CloudWatch Log Event that will be + * printed to the terminal + */ +interface CloudWatchLogEvent { + /** + * The log event message + */ + readonly message: string; + + /** + * The name of the log group + */ + readonly logGroupName: string; + + /** + * The time at which the event occurred + */ + readonly timestamp: Date; +} + +/** + * Configuration tracking information on the log groups that are + * being monitored + */ +interface LogGroupsAccessSettings { + /** + * The SDK for a given environment (account/region) + */ + readonly sdk: ISDK; + + /** + * A map of log groups and associated startTime in a given account. + * + * The monitor will read events from the log group starting at the + * associated startTime + */ + readonly logGroupsStartTimes: { [logGroupName: string]: number }; +} + +export class CloudWatchLogEventMonitor { + /** + * Determines which events not to display + */ + private startTime: number; + + /** + * Map of environment (account:region) to LogGroupsAccessSettings + */ + private readonly envsLogGroupsAccessSettings = new Map(); + + private active = false; + + constructor(startTime?: Date) { + this.startTime = startTime?.getTime() ?? Date.now(); + } + + /** + * resume reading/printing events + */ + public activate(): void { + this.active = true; + this.scheduleNextTick(0); + } + + /** + * deactivates the monitor so no new events are read + * use case for this is when we are in the middle of performing a deployment + * and don't want to interweave all the logs together with the CFN + * deployment logs + * + * Also resets the start time to be when the new deployment was triggered + * and clears the list of tracked log groups + */ + public deactivate(): void { + this.active = false; + this.startTime = Date.now(); + this.envsLogGroupsAccessSettings.clear(); + } + + /** + * Adds CloudWatch log groups to read log events from. + * Since we could be watching multiple stacks that deploy to + * multiple environments (account+region), we need to store a list of log groups + * per env along with the SDK object that has access to read from + * that environment. + */ + public addLogGroups(env: cxapi.Environment, sdk: ISDK, logGroupNames: string[]): void { + const awsEnv = `${env.account}:${env.region}`; + const logGroupsStartTimes = logGroupNames.reduce((acc, groupName) => { + acc[groupName] = this.startTime; + return acc; + }, {} as { [logGroupName: string]: number }); + this.envsLogGroupsAccessSettings.set(awsEnv, { + sdk, + logGroupsStartTimes: { + ...this.envsLogGroupsAccessSettings.get(awsEnv)?.logGroupsStartTimes, + ...logGroupsStartTimes, + }, + }); + } + + private scheduleNextTick(sleep: number): void { + setTimeout(() => void(this.tick()), sleep); + } + + private async tick(): Promise { + if (!this.active) { + return; + } + try { + const events = flatten(await this.readNewEvents()); + events.forEach(event => { + this.print(event); + }); + } catch (e) { + error('Error occurred while monitoring logs: %s', e); + } + + this.scheduleNextTick(SLEEP); + } + + /** + * Reads all new log events from a set of CloudWatch Log Groups + * in parallel + */ + private async readNewEvents(): Promise>> { + const promises: Array>> = []; + for (const settings of this.envsLogGroupsAccessSettings.values()) { + for (const group of Object.keys(settings.logGroupsStartTimes)) { + promises.push(this.readEventsFromLogGroup(settings, group)); + } + } + return Promise.all(promises); + } + + /** + * Print out a cloudwatch event + */ + private print(event: CloudWatchLogEvent): void { + print(util.format('[%s] %s %s', + chalk.blue(event.logGroupName), + chalk.yellow(event.timestamp.toLocaleTimeString()), + event.message.trim())); + } + + /** + * Reads all new log events from a CloudWatch Log Group + * starting at either the time the hotswap was triggered or + * when the last event was read on the previous tick + */ + private async readEventsFromLogGroup( + logGroupsAccessSettings: LogGroupsAccessSettings, + logGroupName: string, + ): Promise> { + const events: CloudWatchLogEvent[] = []; + + // log events from some service are ingested faster than others + // so we need to track the start/end time for each log group individually + // to make sure that we process all events from each log group + const startTime = logGroupsAccessSettings.logGroupsStartTimes[logGroupName] ?? this.startTime; + let endTime = startTime; + try { + const response = await logGroupsAccessSettings.sdk.cloudWatchLogs().filterLogEvents({ + logGroupName: logGroupName, + limit: 100, + startTime: startTime, + }).promise(); + const filteredEvents = response.events ?? []; + + for (const event of filteredEvents) { + if (event.message) { + events.push({ + message: event.message, + logGroupName, + timestamp: event.timestamp ? new Date(event.timestamp) : new Date(), + }); + + if (event.timestamp && endTime < event.timestamp) { + endTime = event.timestamp; + } + + } + } + // if we have > 100 events let the user know some + // messages have been supressed. We are essentially + // showing them a sampling (10000 events printed out is not very useful) + if (filteredEvents.length > 0 && response.nextToken) { + events.push({ + message: '>>> `watch` shows only the first 100 log messages - the rest have been truncated...', + logGroupName, + timestamp: new Date(endTime), + }); + } + } catch (e) { + // with Lambda functions the CloudWatch is not created + // until something is logged, so just keep polling until + // there is somthing to find + if (e.code === 'ResourceNotFoundException') { + return []; + } + throw e; + } + logGroupsAccessSettings.logGroupsStartTimes[logGroupName] = endTime + 1; + return events; + } +} diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts index 750acea174e05..141dbb2f7c3f4 100644 --- a/packages/aws-cdk/lib/cdk-toolkit.ts +++ b/packages/aws-cdk/lib/cdk-toolkit.ts @@ -11,6 +11,8 @@ import { Bootstrapper, BootstrapEnvironmentOptions } from './api/bootstrap'; import { CloudFormationDeployments } from './api/cloudformation-deployments'; import { CloudAssembly, DefaultSelection, ExtendedStackSelection, StackCollection, StackSelector } from './api/cxapp/cloud-assembly'; import { CloudExecutable } from './api/cxapp/cloud-executable'; +import { findCloudWatchLogGroups } from './api/logs/find-cloudwatch-logs'; +import { CloudWatchLogEventMonitor } from './api/logs/logs-monitor'; import { StackActivityProgress } from './api/util/cloudformation/stack-activity-monitor'; import { printSecurityDiff, printStackDiff, RequireApproval } from './diff'; import { data, debug, error, highlight, print, success, warning } from './logging'; @@ -242,6 +244,10 @@ export class CdkToolkit { error('\n ❌ %s failed: %s', chalk.bold(stack.displayName), e); throw e; } finally { + if (options.cloudWatchLogMonitor) { + const foundLogGroupsResult = await findCloudWatchLogGroups(this.props.sdkProvider, stack); + options.cloudWatchLogMonitor.addLogGroups(foundLogGroupsResult.env, foundLogGroupsResult.sdk, foundLogGroupsResult.logGroupNames); + } // If an outputs file has been specified, create the file path and write stack outputs to it once. // Outputs are written after all stacks have been deployed. If a stack deployment fails, // all of the outputs from successfully deployed stacks before the failure will still be written. @@ -304,10 +310,12 @@ export class CdkToolkit { // -------------- -------- 'cdk deploy' done -------------- 'cdk deploy' done -------------- let latch: 'pre-ready' | 'open' | 'deploying' | 'queued' = 'pre-ready'; + const cloudWatchLogMonitor = options.traceLogs ? new CloudWatchLogEventMonitor() : undefined; const deployAndWatch = async () => { latch = 'deploying'; + cloudWatchLogMonitor?.deactivate(); - await this.invokeDeployFromWatch(options); + await this.invokeDeployFromWatch(options, cloudWatchLogMonitor); // If latch is still 'deploying' after the 'await', that's fine, // but if it's 'queued', that means we need to deploy again @@ -316,9 +324,10 @@ export class CdkToolkit { // and thinks the above 'while' condition is always 'false' without the cast latch = 'deploying'; print("Detected file changes during deployment. Invoking 'cdk deploy' again"); - await this.invokeDeployFromWatch(options); + await this.invokeDeployFromWatch(options, cloudWatchLogMonitor); } latch = 'open'; + cloudWatchLogMonitor?.activate(); }; chokidar.watch(watchIncludes, { @@ -594,7 +603,7 @@ export class CdkToolkit { : (options.returnRootDirIfEmpty ? [options.rootDir] : []); } - private async invokeDeployFromWatch(options: WatchOptions): Promise { + private async invokeDeployFromWatch(options: WatchOptions, cloudWatchLogMonitor?: CloudWatchLogEventMonitor): Promise { // 'watch' has different defaults than regular 'deploy' const hotswap = options.hotswap === undefined ? true : options.hotswap; const deployOptions: DeployOptions = { @@ -604,6 +613,7 @@ export class CdkToolkit { // we need to make sure to not call 'deploy' with 'watch' again, // as that would lead to a cycle watch: false, + cloudWatchLogMonitor, cacheCloudAssembly: false, hotswap: hotswap, extraUserAgent: `cdk-watch/hotswap-${hotswap ? 'on' : 'off'}`, @@ -745,6 +755,14 @@ interface WatchOptions { * @default - nothing extra is appended to the User-Agent header */ readonly extraUserAgent?: string; + + /** + * Whether to show CloudWatch logs for hotswapped resources + * locally in the users terminal + * + * @default - false + */ + readonly traceLogs?: boolean; } export interface DeployOptions extends WatchOptions { @@ -815,6 +833,14 @@ export interface DeployOptions extends WatchOptions { * @default true */ readonly cacheCloudAssembly?: boolean; + + /** + * Allows adding CloudWatch log groups to the log monitor via + * cloudWatchLogMonitor.setLogGroups(); + * + * @default - not monitoring CloudWatch logs + */ + readonly cloudWatchLogMonitor?: CloudWatchLogEventMonitor; } export interface DestroyOptions { diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index e468828a130ec..3480b90dbd3a1 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -39,7 +39,7 @@ "devDependencies": { "@aws-cdk/core": "0.0.0", "@octokit/rest": "^18.12.0", - "@types/archiver": "^5.3.0", + "@types/archiver": "^5.3.1", "@types/fs-extra": "^8.1.2", "@types/glob": "^7.2.0", "@types/jest": "^27.4.0", @@ -50,7 +50,7 @@ "@types/semver": "^7.3.9", "@types/sinon": "^9.0.11", "@types/table": "^6.0.0", - "@types/uuid": "^8.3.3", + "@types/uuid": "^8.3.4", "@types/wrap-ansi": "^3.0.0", "@types/yargs": "^15.0.14", "aws-sdk-mock": "^5.5.1", @@ -59,7 +59,7 @@ "jest": "^27.4.7", "make-runnable": "^1.3.10", "mockery": "^2.1.0", - "nock": "^13.2.1", + "nock": "^13.2.2", "@aws-cdk/pkglint": "0.0.0", "sinon": "^9.2.4", "ts-jest": "^27.1.2", @@ -71,7 +71,7 @@ "@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.50.0", + "@jsii/check-node": "1.52.1", "archiver": "^5.3.0", "aws-sdk": "^2.979.0", "camelcase": "^6.3.0", @@ -87,7 +87,7 @@ "proxy-agent": "^5.0.0", "semver": "^7.3.5", "source-map-support": "^0.5.21", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "table": "^6.8.0", "uuid": "^8.3.2", "wrap-ansi": "^7.0.0", diff --git a/packages/aws-cdk/test/api/bootstrap2.test.ts b/packages/aws-cdk/test/api/bootstrap2.test.ts index bf6f6e836a79a..42b4f24d0a771 100644 --- a/packages/aws-cdk/test/api/bootstrap2.test.ts +++ b/packages/aws-cdk/test/api/bootstrap2.test.ts @@ -172,8 +172,7 @@ describe('Bootstrapping v2', () => { parameters: { cloudFormationExecutionPolicies: ['arn:policy'], }, - })) - .rejects.toThrow('Not downgrading existing bootstrap stack'); + })).resolves.toEqual(expect.objectContaining({ noOp: true })); }); test('bootstrap template has the right exports', async () => { diff --git a/packages/aws-cdk/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.ts b/packages/aws-cdk/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.ts new file mode 100644 index 0000000000000..9aef8b8778cf0 --- /dev/null +++ b/packages/aws-cdk/test/api/hotswap/lambda-functions-docker-hotswap-deployments.test.ts @@ -0,0 +1,67 @@ +import { Lambda } from 'aws-sdk'; +import * as setup from './hotswap-test-setup'; + +let mockUpdateLambdaCode: (params: Lambda.Types.UpdateFunctionCodeRequest) => Lambda.Types.FunctionConfiguration; +let mockTagResource: (params: Lambda.Types.TagResourceRequest) => {}; +let mockUntagResource: (params: Lambda.Types.UntagResourceRequest) => {}; +let hotswapMockSdkProvider: setup.HotswapMockSdkProvider; + +beforeEach(() => { + hotswapMockSdkProvider = setup.setupHotswapTests(); + mockUpdateLambdaCode = jest.fn(); + mockTagResource = jest.fn(); + mockUntagResource = jest.fn(); + hotswapMockSdkProvider.stubLambda({ + updateFunctionCode: mockUpdateLambdaCode, + tagResource: mockTagResource, + untagResource: mockUntagResource, + }); +}); + +test('calls the updateLambdaCode() API when it receives only a code difference in a Lambda function', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ImageUri: 'current-image', + }, + FunctionName: 'my-function', + }, + Metadata: { + 'aws:asset:path': 'old-path', + }, + }, + }, + }); + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ImageUri: 'new-image', + }, + FunctionName: 'my-function', + }, + Metadata: { + 'aws:asset:path': 'new-path', + }, + }, + }, + }, + }); + + // WHEN + const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact); + + // THEN + expect(deployStackResult).not.toBeUndefined(); + expect(mockUpdateLambdaCode).toHaveBeenCalledWith({ + FunctionName: 'my-function', + ImageUri: 'new-image', + }); +}); diff --git a/packages/aws-cdk/test/api/hotswap/lambda-functions-inline-hotswap-deployments.test.ts b/packages/aws-cdk/test/api/hotswap/lambda-functions-inline-hotswap-deployments.test.ts new file mode 100644 index 0000000000000..13554cc655dcb --- /dev/null +++ b/packages/aws-cdk/test/api/hotswap/lambda-functions-inline-hotswap-deployments.test.ts @@ -0,0 +1,148 @@ +import { Lambda } from 'aws-sdk'; +import * as setup from './hotswap-test-setup'; + +let mockUpdateLambdaCode: (params: Lambda.Types.UpdateFunctionCodeRequest) => Lambda.Types.FunctionConfiguration; +let mockTagResource: (params: Lambda.Types.TagResourceRequest) => {}; +let mockUntagResource: (params: Lambda.Types.UntagResourceRequest) => {}; +let hotswapMockSdkProvider: setup.HotswapMockSdkProvider; + +beforeEach(() => { + hotswapMockSdkProvider = setup.setupHotswapTests(); + mockUpdateLambdaCode = jest.fn(); + mockTagResource = jest.fn(); + mockUntagResource = jest.fn(); + hotswapMockSdkProvider.stubLambda({ + updateFunctionCode: mockUpdateLambdaCode, + tagResource: mockTagResource, + untagResource: mockUntagResource, + }); +}); + +test('calls the updateLambdaCode() API when it receives only a code difference in a Lambda function (Inline Node.js code)', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: 'exports.handler = () => {return true}', + }, + Runtime: 'nodejs14.x', + FunctionName: 'my-function', + }, + }, + }, + }); + const newCode = 'exports.handler = () => {return false}'; + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: newCode, + }, + Runtime: 'nodejs14.x', + FunctionName: 'my-function', + }, + }, + }, + }, + }); + + // WHEN + const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact); + + // THEN + expect(deployStackResult).not.toBeUndefined(); + expect(mockUpdateLambdaCode).toHaveBeenCalledWith({ + FunctionName: 'my-function', + ZipFile: expect.any(Buffer), + }); +}); + +test('calls the updateLambdaCode() API when it receives only a code difference in a Lambda function (Inline Python code)', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: 'def handler(event, context):\n return True', + }, + Runtime: 'python3.9', + FunctionName: 'my-function', + }, + }, + }, + }); + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: 'def handler(event, context):\n return False', + }, + Runtime: 'python3.9', + FunctionName: 'my-function', + }, + }, + }, + }, + }); + + // WHEN + const deployStackResult = await hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact); + + // THEN + expect(deployStackResult).not.toBeUndefined(); + expect(mockUpdateLambdaCode).toHaveBeenCalledWith({ + FunctionName: 'my-function', + ZipFile: expect.any(Buffer), + }); +}); + +test('throw a CfnEvaluationException when it receives an unsupported function runtime', async () => { + // GIVEN + setup.setCurrentCfnStackTemplate({ + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: 'def handler(event:, context:) true end', + }, + Runtime: 'ruby2.7', + FunctionName: 'my-function', + }, + }, + }, + }); + const cdkStackArtifact = setup.cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + Code: { + ZipFile: 'def handler(event:, context:) false end', + }, + Runtime: 'ruby2.7', + FunctionName: 'my-function', + }, + }, + }, + }, + }); + + // WHEN + const tryHotswap = hotswapMockSdkProvider.tryHotswapDeployment(cdkStackArtifact); + + // THEN + await expect(tryHotswap).rejects.toThrow('runtime ruby2.7 is unsupported, only node.js and python runtimes are currently supported.'); +}); diff --git a/packages/aws-cdk/test/api/logs/find-cloudwatch-logs.test.ts b/packages/aws-cdk/test/api/logs/find-cloudwatch-logs.test.ts new file mode 100644 index 0000000000000..c4402c37cc4cd --- /dev/null +++ b/packages/aws-cdk/test/api/logs/find-cloudwatch-logs.test.ts @@ -0,0 +1,298 @@ +import * as cxapi from '@aws-cdk/cx-api'; +import { CloudFormation } from 'aws-sdk'; +import { findCloudWatchLogGroups } from '../../../lib/api/logs/find-cloudwatch-logs'; +import { testStack, TestStackArtifact } from '../../util'; +import { MockSdkProvider } from '../../util/mock-sdk'; + +let logsMockSdkProvider: LogsMockSdkProvider; +let mockGetEndpointSuffix: () => string; + +beforeEach(() => { + logsMockSdkProvider = new LogsMockSdkProvider(); + mockGetEndpointSuffix = jest.fn(() => 'amazonaws.com'); + logsMockSdkProvider.stubGetEndpointSuffix(mockGetEndpointSuffix); + // clear the array + currentCfnStackResources.splice(0); +}); + +test('add log groups from lambda function', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + Properties: { + FunctionName: 'my-function', + }, + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('Func', 'AWS::Lambda::Function', 'my-function')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['/aws/lambda/my-function']); +}); + +test('add log groups from lambda function without physical name', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + Func: { + Type: 'AWS::Lambda::Function', + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('Func', 'AWS::Lambda::Function', 'my-function')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['/aws/lambda/my-function']); +}); + +test('empty template', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: {}, + }); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual([]); +}); + +test('add log groups from ECS Task Definitions', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + LogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: 'log_group', + }, + }, + Def: { + Type: 'AWS::ECS::TaskDefinition', + Properties: { + Family: 'app', + ContainerDefinitions: [ + { + LogConfiguration: { + LogDriver: 'awslogs', + Options: { + 'awslogs-group': { Ref: 'LogGroup' }, + }, + }, + }, + ], + }, + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('LogGroup', 'AWS::Logs::LogGroup', 'log_group')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['log_group']); +}); + +test('add log groups from State Machines', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + LogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: 'log_group', + }, + }, + Def: { + Type: 'AWS::StepFunctions::StateMachine', + Properties: { + LoggingConfiguration: { + Destinations: [ + { + CloudWatchLogsLogGroup: { + LogGroupArn: { + 'Fn::GetAtt': ['LogGroup', 'Arn'], + }, + }, + }, + ], + }, + }, + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('LogGroup', 'AWS::Logs::LogGroup', 'log_group')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['log_group']); +}); + +test('excluded log groups are not added', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + LogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: 'log_group', + }, + }, + LogGroup2: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: 'log_group2', + }, + }, + Def: { + Type: 'AWS::CodeBuild::Project', + Properties: { + PojectName: 'project', + LogsConfig: { + CloudWatchLogs: { + GroupName: { Ref: 'LogGroup' }, + }, + }, + }, + }, + FlowLog: { + Type: 'AWS::EC2::FlowLog', + Properties: { + LogDestination: { Ref: 'LogGroup' }, + }, + }, + FlowLog2: { + Type: 'AWS::EC2::FlowLog', + Properties: { + LogDestination: { + 'Fn::GetAtt': ['LogGroup2', 'Arn'], + }, + }, + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('LogGroup', 'AWS::Logs::LogGroup', 'log_group')); + pushStackResourceSummaries(stackSummaryOf('LogGroup2', 'AWS::Logs::LogGroup', 'log_group2')); + pushStackResourceSummaries(stackSummaryOf('FlowLog', 'AWS::EC2::FlowLog', 'flow_log')); + pushStackResourceSummaries(stackSummaryOf('FlowLog2', 'AWS::EC2::FlowLog', 'flow_log2')); + pushStackResourceSummaries(stackSummaryOf('Def', 'AWS::CodeBuild:Project', 'project')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual([]); +}); + +test('unassociated log groups are added', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + LogGroup: { + Type: 'AWS::Logs::LogGroup', + Properties: { + LogGroupName: 'log_group', + }, + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('LogGroup', 'AWS::Logs::LogGroup', 'log_group')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['log_group']); +}); + +test('log groups without physical names are added', async () => { + // GIVEN + const cdkStackArtifact = cdkStackArtifactOf({ + template: { + Resources: { + LogGroup: { + Type: 'AWS::Logs::LogGroup', + }, + }, + }, + }); + pushStackResourceSummaries(stackSummaryOf('LogGroup', 'AWS::Logs::LogGroup', 'log_group')); + + // WHEN + const result = await findCloudWatchLogGroups(logsMockSdkProvider.mockSdkProvider, cdkStackArtifact); + + // THEN + expect(result.logGroupNames).toEqual(['log_group']); +}); + +const STACK_NAME = 'withouterrors'; +const currentCfnStackResources: CloudFormation.StackResourceSummary[] = []; + +function pushStackResourceSummaries(...items: CloudFormation.StackResourceSummary[]) { + currentCfnStackResources.push(...items); +} + +function stackSummaryOf(logicalId: string, resourceType: string, physicalResourceId: string): CloudFormation.StackResourceSummary { + return { + LogicalResourceId: logicalId, + PhysicalResourceId: physicalResourceId, + ResourceType: resourceType, + ResourceStatus: 'CREATE_COMPLETE', + LastUpdatedTimestamp: new Date(), + }; +} + +function cdkStackArtifactOf(testStackArtifact: Partial = {}): cxapi.CloudFormationStackArtifact { + return testStack({ + stackName: STACK_NAME, + ...testStackArtifact, + }); +} + +class LogsMockSdkProvider { + public readonly mockSdkProvider: MockSdkProvider; + + constructor() { + this.mockSdkProvider = new MockSdkProvider({ realSdk: false }); + + this.mockSdkProvider.stubCloudFormation({ + listStackResources: ({ StackName: stackName }) => { + if (stackName !== STACK_NAME) { + throw new Error(`Expected Stack name in listStackResources() call to be: '${STACK_NAME}', but received: ${stackName}'`); + } + return { + StackResourceSummaries: currentCfnStackResources, + }; + }, + }); + } + + public stubGetEndpointSuffix(stub: () => string) { + this.mockSdkProvider.stubGetEndpointSuffix(stub); + } +} diff --git a/packages/aws-cdk/test/api/logs/logs-monitor.test.ts b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts new file mode 100644 index 0000000000000..becb3d97dfbf3 --- /dev/null +++ b/packages/aws-cdk/test/api/logs/logs-monitor.test.ts @@ -0,0 +1,71 @@ +import { blue, yellow } from 'chalk'; +import { CloudWatchLogEventMonitor } from '../../../lib/api/logs/logs-monitor'; +import { sleep } from '../../integ/helpers/aws'; +import { MockSdk } from '../../util/mock-sdk'; + +let sdk: MockSdk; +let stderrMock: jest.SpyInstance; +let monitor: CloudWatchLogEventMonitor; +beforeEach(() => { + monitor = new CloudWatchLogEventMonitor(new Date(T100)); + stderrMock = jest.spyOn(process.stderr, 'write').mockImplementation(() => { return true; }); + sdk = new MockSdk(); +}); + +afterAll(() => { + stderrMock.mockRestore(); + monitor.deactivate(); +}); + +let TIMESTAMP: number; +let HUMAN_TIME: string; + +beforeAll(() => { + TIMESTAMP = new Date().getTime(); + HUMAN_TIME = new Date(TIMESTAMP).toLocaleTimeString(); +}); + +test('continue to the next page if it exists', async () => { + // GIVEN + sdk.stubCloudWatchLogs({ + filterLogEvents() { + return { + events: [event(102, 'message')], + nextToken: 'some-token', + }; + }, + }); + monitor.addLogGroups( + { + name: 'name', + account: '11111111111', + region: 'us-east-1', + }, + sdk, + ['loggroup'], + ); + // WHEN + monitor.activate(); + // need time for the log processing to occur + await sleep(1000); + + // THEN + expect(stderrMock).toHaveBeenCalledTimes(2); + expect(stderrMock.mock.calls[0][0]).toContain( + `[${blue('loggroup')}] ${yellow(HUMAN_TIME)} message`, + ); + expect(stderrMock.mock.calls[1][0]).toContain( + `[${blue('loggroup')}] ${yellow(new Date(T100).toLocaleTimeString())} >>> \`watch\` shows only the first 100 log messages - the rest have been truncated...`, + ); +}); + +const T0 = 1597837230504; +const T100 = T0 + 100 * 1000; +function event(nr: number, message: string): AWS.CloudWatchLogs.FilteredLogEvent { + return { + eventId: `${nr}`, + message, + timestamp: new Date(T0 * nr * 1000).getTime(), + ingestionTime: new Date(T0 * nr * 1000).getTime(), + }; +} diff --git a/packages/aws-cdk/test/cdk-toolkit.test.ts b/packages/aws-cdk/test/cdk-toolkit.test.ts index 7b8f96d5d948c..c7ee3b87130fc 100644 --- a/packages/aws-cdk/test/cdk-toolkit.test.ts +++ b/packages/aws-cdk/test/cdk-toolkit.test.ts @@ -127,6 +127,13 @@ describe('readCurrentTemplate', () => { }, }, }, + { + stackName: 'Test-Stack-A', + template, + properties: { + assumeRoleArn: 'bloop:${AWS::Region}:${AWS::AccountId}', + }, + }, ], }); mockForEnvironment = jest.fn().mockImplementation(() => { return { sdk: mockCloudExecutable.sdkProvider.sdk, didAssumeRole: true }; }); @@ -145,6 +152,11 @@ describe('readCurrentTemplate', () => { StackStatus: 'CREATE_COMPLETE', CreationTime: new Date(), }, + { + StackName: 'Test-Stack-A', + StackStatus: 'CREATE_COMPLETE', + CreationTime: new Date(), + }, ], }; }, @@ -329,6 +341,38 @@ describe('readCurrentTemplate', () => { assumeRoleArn: 'bloop:here:123456789012', }); }); + + test('do not print warnings if lookup role not provided in stack artifact', async () => { + // GIVEN + mockCloudExecutable.sdkProvider.stubSSM({ + getParameter() { + return {}; + }, + }); + const cdkToolkit = new CdkToolkit({ + cloudExecutable: mockCloudExecutable, + configuration: mockCloudExecutable.configuration, + sdkProvider: mockCloudExecutable.sdkProvider, + cloudFormation: new CloudFormationDeployments({ sdkProvider: mockCloudExecutable.sdkProvider }), + }); + + // WHEN + await cdkToolkit.deploy({ + selector: { patterns: ['Test-Stack-A'] }, + }); + + // THEN + expect(flatten(stderrMock.mock.calls)).not.toEqual(expect.arrayContaining([ + expect.stringMatching(/Could not assume/), + expect.stringMatching(/please upgrade to bootstrap version/), + ])); + expect(mockCloudExecutable.sdkProvider.sdk.ssm).not.toHaveBeenCalled(); + expect(mockForEnvironment.mock.calls.length).toEqual(2); + expect(mockForEnvironment.mock.calls[0][2]).toEqual({ + assumeRoleArn: undefined, + assumeRoleExternalId: undefined, + }); + }); }); describe('deploy', () => { diff --git a/packages/aws-cdk/test/util/mock-sdk.ts b/packages/aws-cdk/test/util/mock-sdk.ts index 960d3c65e01ab..a1ed61a431366 100644 --- a/packages/aws-cdk/test/util/mock-sdk.ts +++ b/packages/aws-cdk/test/util/mock-sdk.ts @@ -114,6 +114,10 @@ export class MockSdkProvider extends SdkProvider { (this.sdk as any).codeBuild = jest.fn().mockReturnValue(partialAwsService(stubs)); } + public stubCloudWatchLogs(stubs: SyncHandlerSubsetOf) { + (this.sdk as any).cloudWatchLogs = jest.fn().mockReturnValue(partialAwsService(stubs)); + } + public stubGetEndpointSuffix(stub: () => string) { this.sdk.getEndpointSuffix = stub; } @@ -134,6 +138,7 @@ export class MockSdk implements ISDK { public readonly kms = jest.fn(); public readonly stepFunctions = jest.fn(); public readonly codeBuild = jest.fn(); + public readonly cloudWatchLogs = jest.fn(); public readonly getEndpointSuffix = jest.fn(); public readonly appendCustomUserAgent = jest.fn(); public readonly removeCustomUserAgent = jest.fn(); @@ -149,6 +154,13 @@ export class MockSdk implements ISDK { this.cloudFormation.mockReturnValue(partialAwsService(stubs)); } + /** + * Replace the CloudWatch client with the given object + */ + public stubCloudWatchLogs(stubs: SyncHandlerSubsetOf) { + this.cloudWatchLogs.mockReturnValue(partialAwsService(stubs)); + } + /** * Replace the ECR client with the given object */ diff --git a/packages/awslint/package.json b/packages/awslint/package.json index 8a480535575ae..8245425a159d7 100644 --- a/packages/awslint/package.json +++ b/packages/awslint/package.json @@ -18,11 +18,11 @@ "awslint": "bin/awslint" }, "dependencies": { - "@jsii/spec": "^1.50.0", + "@jsii/spec": "^1.52.1", "camelcase": "^6.3.0", "chalk": "^4", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.50.0", + "jsii-reflect": "^1.52.1", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/packages/cdk-assets/lib/private/handlers/files.ts b/packages/cdk-assets/lib/private/handlers/files.ts index 7433d7d9be517..cf77eda43dddc 100644 --- a/packages/cdk-assets/lib/private/handlers/files.ts +++ b/packages/cdk-assets/lib/private/handlers/files.ts @@ -10,6 +10,13 @@ import { pathExists } from '../fs-extra'; import { replaceAwsPlaceholders } from '../placeholders'; import { shell } from '../shell'; +/** + * The size of an empty zip file is 22 bytes + * + * Ref: https://en.wikipedia.org/wiki/ZIP_(file_format) + */ +const EMPTY_ZIP_FILE_SIZE = 22; + export class FileAssetHandler implements IAssetHandler { private readonly fileCacheRoot: string; @@ -74,6 +81,34 @@ export class FileAssetHandler implements IAssetHandler { const publishFile = this.asset.source.executable ? await this.externalPackageFile(this.asset.source.executable) : await this.packageFile(this.asset.source); + // Add a validation to catch the cases where we're accidentally producing an empty ZIP file (or worse, + // an empty file) + if (publishFile.contentType === 'application/zip') { + const fileSize = (await fs.stat(publishFile.packagedPath)).size; + if (fileSize <= EMPTY_ZIP_FILE_SIZE) { + const message = [ + '🚨 WARNING: EMPTY ZIP FILE 🚨', + '', + 'Zipping this asset produced an empty zip file. We do not know the root cause for this yet, and we need your help tracking it down.', + '', + 'Please visit https://github.com/aws/aws-cdk/issues/18459 and tell us:', + 'Your OS version, Nodejs version, CLI version, package manager, what the asset is supposed to contain, whether', + 'or not this error is reproducible, what files are in your cdk.out directory, if you recently changed anything,', + 'and anything else you think might be relevant.', + '', + 'The deployment will continue, but it may fail. You can try removing the cdk.out directory and running the command', + 'again; let us know if that resolves it.', + '', + 'If you meant to produce an empty asset file on purpose, you can add an empty dotfile to the asset for now', + 'to disable this notice.', + ]; + + for (const line of message) { + this.host.emitMessage(EventType.FAIL, line); + } + } + } + this.host.emitMessage(EventType.UPLOAD, `Upload ${s3Url}`); const params = Object.assign({}, { @@ -101,11 +136,11 @@ export class FileAssetHandler implements IAssetHandler { const packagedPath = path.join(this.fileCacheRoot, `${this.asset.id.assetId}.zip`); if (await pathExists(packagedPath)) { - this.host.emitMessage(EventType.CACHED, `From cache ${path}`); + this.host.emitMessage(EventType.CACHED, `From cache ${packagedPath}`); return { packagedPath, contentType }; } - this.host.emitMessage(EventType.BUILD, `Zip ${fullPath} -> ${path}`); + this.host.emitMessage(EventType.BUILD, `Zip ${fullPath} -> ${packagedPath}`); await zipDirectory(fullPath, packagedPath); return { packagedPath, contentType }; } else { @@ -149,9 +184,19 @@ async function objectExists(s3: AWS.S3, bucket: string, key: string) { * prefix, and limiting results to 1. Since the list operation returns keys ordered by binary * UTF-8 representation, the key we are looking for is guaranteed to always be the first match * returned if it exists. + * + * If the file is too small, we discount it as a cache hit. There is an issue + * somewhere that sometimes produces empty zip files, and we would otherwise + * never retry building those assets without users having to manually clear + * their bucket, which is a bad experience. */ const response = await s3.listObjectsV2({ Bucket: bucket, Prefix: key, MaxKeys: 1 }).promise(); - return response.Contents != null && response.Contents.some(object => object.Key === key); + return ( + response.Contents != null && + response.Contents.some( + (object) => object.Key === key && (object.Size == null || object.Size > EMPTY_ZIP_FILE_SIZE), + ) + ); } diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index 07e1ae23e6546..901937ed9ab0e 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -30,7 +30,7 @@ }, "license": "Apache-2.0", "devDependencies": { - "@types/archiver": "^5.3.0", + "@types/archiver": "^5.3.1", "@types/glob": "^7.2.0", "@types/jest": "^27.4.0", "@types/mime": "^2.0.3", diff --git a/packages/cdk-assets/test/fake-listener.ts b/packages/cdk-assets/test/fake-listener.ts index 46b7f31a3ecc7..7aef7fbe9d9f6 100644 --- a/packages/cdk-assets/test/fake-listener.ts +++ b/packages/cdk-assets/test/fake-listener.ts @@ -1,6 +1,7 @@ import { IPublishProgressListener, EventType, IPublishProgress } from '../lib/progress'; export class FakeListener implements IPublishProgressListener { + public readonly types = new Array(); public readonly messages = new Array(); constructor(private readonly doAbort = false) { diff --git a/packages/cdk-assets/test/files.test.ts b/packages/cdk-assets/test/files.test.ts index 7616482d43944..9ef52ef8a21a8 100644 --- a/packages/cdk-assets/test/files.test.ts +++ b/packages/cdk-assets/test/files.test.ts @@ -2,13 +2,20 @@ jest.mock('child_process'); import { Manifest } from '@aws-cdk/cloud-assembly-schema'; import * as mockfs from 'mock-fs'; -import { AssetManifest, AssetPublishing } from '../lib'; +import { AssetPublishing, AssetManifest } from '../lib'; import { FakeListener } from './fake-listener'; import { mockAws, mockedApiFailure, mockedApiResult, mockUpload } from './mock-aws'; import { mockSpawn } from './mock-child_process'; const ABS_PATH = '/simple/cdk.out/some_external_file'; +const DEFAULT_DESTINATION = { + region: 'us-north-50', + assumeRoleArn: 'arn:aws:role', + bucketName: 'some_bucket', + objectKey: 'some_key', +}; + let aws: ReturnType; beforeEach(() => { jest.resetAllMocks(); @@ -21,19 +28,12 @@ beforeEach(() => { source: { path: 'some_file', }, - destinations: { - theDestination: { - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - bucketName: 'some_bucket', - objectKey: 'some_key', - }, - }, + destinations: { theDestination: DEFAULT_DESTINATION }, }, }, }), '/simple/cdk.out/some_file': 'FILE_CONTENTS', - [ABS_PATH]: 'FILE_CONTENTS', + [ABS_PATH]: 'ZIP_FILE_THAT_IS_DEFINITELY_NOT_EMPTY', '/abs/cdk.out/assets.json': JSON.stringify({ version: Manifest.version(), files: { @@ -41,14 +41,7 @@ beforeEach(() => { source: { path: '/simple/cdk.out/some_file', }, - destinations: { - theDestination: { - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - bucketName: 'some_other_bucket', - objectKey: 'some_key', - }, - }, + destinations: { theDestination: { ...DEFAULT_DESTINATION, bucketName: 'some_other_bucket' } }, }, }, }), @@ -59,14 +52,7 @@ beforeEach(() => { source: { executable: ['sometool'], }, - destinations: { - theDestination: { - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - bucketName: 'some_external_bucket', - objectKey: 'some_key', - }, - }, + destinations: { theDestination: { ...DEFAULT_DESTINATION, bucketName: 'some_external_bucket' } }, }, }, }), @@ -77,32 +63,31 @@ beforeEach(() => { source: { path: 'plain_text.txt', }, - destinations: { - theDestination: { - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - bucketName: 'some_bucket', - objectKey: 'some_key.txt', - }, - }, + destinations: { theDestination: { ...DEFAULT_DESTINATION, objectKey: 'some_key.txt' } }, }, theImageAsset: { source: { path: 'image.png', }, - destinations: { - theDestination: { - region: 'us-north-50', - assumeRoleArn: 'arn:aws:role', - bucketName: 'some_bucket', - objectKey: 'some_key.png', - }, - }, + destinations: { theDestination: { ...DEFAULT_DESTINATION, objectKey: 'some_key.png' } }, }, }, }), '/types/cdk.out/plain_text.txt': 'FILE_CONTENTS', '/types/cdk.out/image.png': 'FILE_CONTENTS', + '/emptyzip/cdk.out/assets.json': JSON.stringify({ + version: Manifest.version(), + files: { + theTextAsset: { + source: { + path: 'empty_dir', + packaging: 'zip', + }, + destinations: { theDestination: DEFAULT_DESTINATION }, + }, + }, + }), + '/emptyzip/cdk.out/empty_dir': { }, // Empty directory }); aws = mockAws(); @@ -114,6 +99,7 @@ afterEach(() => { test('pass destination properties to AWS client', async () => { const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws, throwOnError: false }); + aws.mockS3.listObjectsV2 = mockedApiResult({}); await pub.publish(); @@ -127,6 +113,7 @@ test('Do nothing if file already exists', async () => { const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key' }] }); + aws.mockS3.upload = mockUpload(); await pub.publish(); expect(aws.mockS3.listObjectsV2).toHaveBeenCalledWith(expect.objectContaining({ @@ -134,8 +121,21 @@ test('Do nothing if file already exists', async () => { Prefix: 'some_key', MaxKeys: 1, })); + expect(aws.mockS3.upload).not.toHaveBeenCalled(); +}); + +test('tiny file does not count as cache hit', async () => { + const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); + + aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: [{ Key: 'some_key', Size: 5 }] }); + aws.mockS3.upload = mockUpload(); + + await pub.publish(); + + expect(aws.mockS3.upload).toHaveBeenCalled(); }); + test('upload file if new (list returns other key)', async () => { const pub = new AssetPublishing(AssetManifest.fromPath('/simple/cdk.out'), { aws }); @@ -310,6 +310,18 @@ test('correctly identify asset path if path is absolute', async () => { expect(true).toBeTruthy(); // No exception, satisfy linter }); +test('empty directory prints failures', async () => { + const progressListener = new FakeListener(); + const pub = new AssetPublishing(AssetManifest.fromPath('/emptyzip/cdk.out'), { aws, progressListener }); + + aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); + aws.mockS3.upload = mockUpload(); // Should not be hit + + await pub.publish(); + + expect(progressListener.messages).toContainEqual(expect.stringContaining('EMPTY ZIP FILE')); +}); + describe('external assets', () => { let pub: AssetPublishing; beforeEach(() => { @@ -330,7 +342,7 @@ describe('external assets', () => { test('upload external asset correctly', async () => { aws.mockS3.listObjectsV2 = mockedApiResult({ Contents: undefined }); - aws.mockS3.upload = mockUpload('FILE_CONTENTS'); + aws.mockS3.upload = mockUpload('ZIP_FILE_THAT_IS_DEFINITELY_NOT_EMPTY'); const expectAllSpawns = mockSpawn({ commandLine: ['sometool'], stdout: ABS_PATH }); await pub.publish(); diff --git a/packages/cdk-assets/test/mock-aws.ts b/packages/cdk-assets/test/mock-aws.ts index 26b4f5d80d914..8ae54b20bc096 100644 --- a/packages/cdk-assets/test/mock-aws.ts +++ b/packages/cdk-assets/test/mock-aws.ts @@ -16,6 +16,7 @@ export function mockAws() { }, ], }); + mockSecretsManager.getSecretValue = mockedApiFailure('NotImplemented', 'You need to supply an implementation for getSecretValue'); return { mockEcr, diff --git a/packages/cdk-assets/test/private/docker-credentials.test.ts b/packages/cdk-assets/test/private/docker-credentials.test.ts index 19160ccd0c880..c4c3f45ce9edf 100644 --- a/packages/cdk-assets/test/private/docker-credentials.test.ts +++ b/packages/cdk-assets/test/private/docker-credentials.test.ts @@ -98,7 +98,9 @@ describe('fetchDockerLoginCredentials', () => { }); test('does not throw on correctly configured raw domain', async () => { - expect(fetchDockerLoginCredentials(aws, config, 'https://secret.example.com/v1/')).resolves; + mockSecretWithSecretString({ username: 'secretUser', secret: 'secretPass' }); + + await expect(fetchDockerLoginCredentials(aws, config, 'https://secret.example.com/v1/')).resolves.toBeTruthy(); }); describe('SecretsManager', () => { diff --git a/packages/cdk-dasm/package.json b/packages/cdk-dasm/package.json index 8f7a02fb677bf..5700d476fc41b 100644 --- a/packages/cdk-dasm/package.json +++ b/packages/cdk-dasm/package.json @@ -28,7 +28,7 @@ }, "license": "Apache-2.0", "dependencies": { - "codemaker": "^1.50.0", + "codemaker": "^1.52.1", "yaml": "1.10.2" }, "devDependencies": { diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 072234cac1852..d53367fd2dfec 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -83,6 +83,7 @@ "@aws-cdk/aws-codestarconnections": "0.0.0", "@aws-cdk/aws-codestarnotifications": "0.0.0", "@aws-cdk/aws-cognito": "0.0.0", + "@aws-cdk/aws-cognito-identitypool": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", @@ -121,6 +122,7 @@ "@aws-cdk/aws-finspace": "0.0.0", "@aws-cdk/aws-fis": "0.0.0", "@aws-cdk/aws-fms": "0.0.0", + "@aws-cdk/aws-forecast": "0.0.0", "@aws-cdk/aws-frauddetector": "0.0.0", "@aws-cdk/aws-fsx": "0.0.0", "@aws-cdk/aws-gamelift": "0.0.0", @@ -135,6 +137,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", + "@aws-cdk/aws-inspectorv2": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", @@ -150,8 +153,10 @@ "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kinesisanalytics": "0.0.0", "@aws-cdk/aws-kinesisanalytics-flink": "0.0.0", + "@aws-cdk/aws-kinesisanalyticsv2": "0.0.0", "@aws-cdk/aws-kinesisfirehose": "0.0.0", "@aws-cdk/aws-kinesisfirehose-destinations": "0.0.0", + "@aws-cdk/aws-kinesisvideo": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lakeformation": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", @@ -253,7 +258,7 @@ "@aws-cdk/region-info": "0.0.0", "constructs": "^3.3.69", "fs-extra": "^9.1.0", - "jsii-reflect": "^1.50.0", + "jsii-reflect": "^1.52.1", "jsonschema": "^1.4.0", "yaml": "1.10.2", "yargs": "^16.2.0" @@ -264,7 +269,7 @@ "@types/yaml": "1.9.7", "@types/yargs": "^15.0.14", "jest": "^27.4.7", - "jsii": "^1.50.0" + "jsii": "^1.52.1" }, "keywords": [ "aws", diff --git a/packages/monocdk/package.json b/packages/monocdk/package.json index d8be50f0a4d9c..d005e103acd8f 100644 --- a/packages/monocdk/package.json +++ b/packages/monocdk/package.json @@ -168,6 +168,7 @@ "@aws-cdk/aws-codestarconnections": "0.0.0", "@aws-cdk/aws-codestarnotifications": "0.0.0", "@aws-cdk/aws-cognito": "0.0.0", + "@aws-cdk/aws-cognito-identitypool": "0.0.0", "@aws-cdk/aws-config": "0.0.0", "@aws-cdk/aws-connect": "0.0.0", "@aws-cdk/aws-cur": "0.0.0", @@ -207,6 +208,7 @@ "@aws-cdk/aws-finspace": "0.0.0", "@aws-cdk/aws-fis": "0.0.0", "@aws-cdk/aws-fms": "0.0.0", + "@aws-cdk/aws-forecast": "0.0.0", "@aws-cdk/aws-frauddetector": "0.0.0", "@aws-cdk/aws-fsx": "0.0.0", "@aws-cdk/aws-gamelift": "0.0.0", @@ -221,6 +223,7 @@ "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-imagebuilder": "0.0.0", "@aws-cdk/aws-inspector": "0.0.0", + "@aws-cdk/aws-inspectorv2": "0.0.0", "@aws-cdk/aws-iot": "0.0.0", "@aws-cdk/aws-iot-actions": "0.0.0", "@aws-cdk/aws-iot1click": "0.0.0", @@ -236,8 +239,10 @@ "@aws-cdk/aws-kinesis": "0.0.0", "@aws-cdk/aws-kinesisanalytics": "0.0.0", "@aws-cdk/aws-kinesisanalytics-flink": "0.0.0", + "@aws-cdk/aws-kinesisanalyticsv2": "0.0.0", "@aws-cdk/aws-kinesisfirehose": "0.0.0", "@aws-cdk/aws-kinesisfirehose-destinations": "0.0.0", + "@aws-cdk/aws-kinesisvideo": "0.0.0", "@aws-cdk/aws-kms": "0.0.0", "@aws-cdk/aws-lakeformation": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", @@ -365,5 +370,6 @@ }, "publishConfig": { "tag": "latest" - } + }, + "preferredCdkCliVersion": "1" } diff --git a/tools/@aws-cdk/cdk-build-tools/package.json b/tools/@aws-cdk/cdk-build-tools/package.json index d9cb3e226a83b..ae33d288d14df 100644 --- a/tools/@aws-cdk/cdk-build-tools/package.json +++ b/tools/@aws-cdk/cdk-build-tools/package.json @@ -56,9 +56,9 @@ "fs-extra": "^9.1.0", "jest": "^27.4.7", "jest-junit": "^13.0.0", - "jsii": "^1.50.0", - "jsii-pacmak": "^1.50.0", - "jsii-reflect": "^1.50.0", + "jsii": "^1.52.1", + "jsii-pacmak": "^1.52.1", + "jsii-reflect": "^1.52.1", "markdownlint-cli": "^0.30.0", "nyc": "^15.1.0", "semver": "^7.3.5", diff --git a/tools/@aws-cdk/cfn2ts/lib/genspec.ts b/tools/@aws-cdk/cfn2ts/lib/genspec.ts index f0fa9ff5f2780..b4283aac0ebb4 100644 --- a/tools/@aws-cdk/cfn2ts/lib/genspec.ts +++ b/tools/@aws-cdk/cfn2ts/lib/genspec.ts @@ -226,6 +226,14 @@ export function attributeDefinition(attributeName: string, spec: schema.Attribut */ export function cloudFormationToScriptName(name: string): string { if (name === 'VPCs') { return 'vpcs'; } + + // Lightsail contains a property called "GetObject", which isn't a jsii-compliant name + // as it conflicts with generated getters in other languages (e.g., Java, C#). + // For now, hard-coding a replacement property name to something that's frankly better anyway. + if (name === 'GetObject') { + name = 'objectAccess'; + } + const ret = codemaker.toCamelCase(name); // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/tools/@aws-cdk/cfn2ts/package.json b/tools/@aws-cdk/cfn2ts/package.json index 373034a94a875..6b7540b5d27c7 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.50.0", + "codemaker": "^1.52.1", "fast-json-patch": "^3.1.0", "fs-extra": "^9.1.0", "yargs": "^16.2.0" diff --git a/tools/@aws-cdk/pkglint/lib/library-creation.ts b/tools/@aws-cdk/pkglint/lib/library-creation.ts index 9dfec23a34a19..8ebe4e8db479d 100644 --- a/tools/@aws-cdk/pkglint/lib/library-creation.ts +++ b/tools/@aws-cdk/pkglint/lib/library-creation.ts @@ -19,7 +19,7 @@ export interface ModuleDefinition { export function createModuleDefinitionFromCfnNamespace(namespace: string): ModuleDefinition { const [moduleFamily, moduleBaseName] = (namespace === 'AWS::Serverless' ? 'AWS::SAM' : namespace).split('::'); - const moduleName = `${moduleFamily}-${moduleBaseName.replace(/V\d+$/, '')}`.toLocaleLowerCase(); + const moduleName = `${moduleFamily}-${moduleBaseName}`.toLocaleLowerCase(); const lowcaseModuleName = moduleBaseName.toLocaleLowerCase(); const packageName = `@aws-cdk/${moduleName}`; diff --git a/yarn.lock b/yarn.lock index c018522afa5ee..bf3c0213efaee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -40,9 +40,9 @@ "@babel/highlight" "^7.16.7" "@babel/compat-data@^7.16.4": - version "7.16.4" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" - integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" + integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== "@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.16.7" @@ -65,12 +65,12 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.16.7", "@babel/generator@^7.7.2": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz#b42bf46a3079fa65e1544135f32e7958f048adbb" - integrity sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg== +"@babel/generator@^7.16.7", "@babel/generator@^7.16.8", "@babel/generator@^7.7.2": + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.16.8" jsesc "^2.5.1" source-map "^0.5.0" @@ -182,10 +182,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz#d372dda9c89fcec340a82630a9f533f2fe15877e" - integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8": + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" + integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -288,25 +288,25 @@ "@babel/types" "^7.16.7" "@babel/traverse@^7.16.7", "@babel/traverse@^7.7.2": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz#dac01236a72c2560073658dd1a285fe4e0865d76" - integrity sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ== + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" + integrity sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" + "@babel/generator" "^7.16.8" "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-function-name" "^7.16.7" "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/parser" "^7.16.8" + "@babel/types" "^7.16.8" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz#4ed19d51f840ed4bd5645be6ce40775fecf03159" - integrity sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg== +"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.16.8" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== dependencies: "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" @@ -568,18 +568,18 @@ "@types/yargs" "^16.0.0" chalk "^4.0.0" -"@jsii/check-node@1.50.0": - version "1.50.0" - resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.50.0.tgz#c1910d39946f8c9e03a936b3c43290088fdf8cd1" - integrity sha512-CkL3EtRIxglzPraC2bR+plEw4pxrbCLUZRjTDxALjhJaO67SWyMUhtHkFerPH9vqIe7rQVkvrv6kJTwpNFRU5Q== +"@jsii/check-node@1.52.1": + version "1.52.1" + resolved "https://registry.npmjs.org/@jsii/check-node/-/check-node-1.52.1.tgz#e14101294593ec41b76812acf5ba9c06e0cbfef2" + integrity sha512-B+vpPwXrKTWA1dBHuStp0sg+YpFZ9APjS6qeDiknMHPMatlT7VA0RVk/LmCLaPZhsfNzByJ+zhRFs0R83zTr1Q== dependencies: chalk "^4.1.2" semver "^7.3.5" -"@jsii/spec@1.50.0", "@jsii/spec@^1.50.0": - version "1.50.0" - resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.50.0.tgz#d69524b7ed3124a3ac57e18c5c0413549a07de6d" - integrity sha512-u5GHFleSgoawkGb2C0vbKnI4w3Xok2/WaNxWojRKeL82UG6/C7E091ezrgQU26Y8l+BIzKK929uc6garfJWn5w== +"@jsii/spec@1.52.1", "@jsii/spec@^1.52.1": + version "1.52.1" + resolved "https://registry.npmjs.org/@jsii/spec/-/spec-1.52.1.tgz#2e44a019e3b5722a96883c42d726b748956c223e" + integrity sha512-Mt5yzqR/DYZhxjOBTuQsstYh0gdlwSWvjTAfUGf5Rp76j8gddkADlrMRFeVrXBy/Y+ccJLUYWMSsEf1Ti6ERcQ== dependencies: jsonschema "^1.4.0" @@ -1575,14 +1575,14 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== -"@types/archiver@^5.3.0": - version "5.3.0" - resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.0.tgz#2b34ba56d4d7102d256b922c7e91e09eab79db6f" - integrity sha512-qJ79qsmq7O/k9FYwsF6O1xVA1PeLV+9Bh3TYkVCu3VzMR6vN9JQkgEOh/rrQ0R+F4Ta+R3thHGewxQtFglwVfg== +"@types/archiver@^5.3.1": + version "5.3.1" + resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.1.tgz#02991e940a03dd1a32678fead4b4ca03d0e387ca" + integrity sha512-wKYZaSXaDvTZuInAWjCeGG7BEAgTWG2zZW0/f7IYFcoHB2X2d9lkVFnrOlXl3W6NrvO6Ml3FLLu8Uksyymcpnw== dependencies: "@types/glob" "*" -"@types/aws-lambda@^8.10.85", "@types/aws-lambda@^8.10.89": +"@types/aws-lambda@^8.10.89": version "8.10.89" resolved "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.89.tgz#22617ecc1eef9571abebb50c947553362da6051b" integrity sha512-jwtSuEZj4rY4R2pAEOXi+RutS8RWbwMzoGlRVukdyOpnfqA/XPkAf8QoGWmg4o/UaNpQ8Mj0Xhkp5SZ1t/Zq4Q== @@ -1694,7 +1694,7 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/jest@^27.0.2", "@types/jest@^27.4.0": +"@types/jest@^27.0.3", "@types/jest@^27.4.0": version "27.4.0" resolved "https://registry.npmjs.org/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" integrity sha512-gHl8XuC1RZ8H2j5sHv/JqsaxXkDDM9iDOgu0Wp8sjs4u/snb2PVehyWXJPr+ORA0RPpgw231mnutWI1+0hgjIQ== @@ -1777,9 +1777,9 @@ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== "@types/prettier@^2.1.5": - version "2.4.2" - resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz#4c62fae93eb479660c3bd93f9d24d561597a8281" - integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== + version "2.4.3" + resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" + integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== "@types/promptly@^3.0.2": version "3.0.2" @@ -1834,10 +1834,10 @@ dependencies: table "*" -"@types/uuid@^8.3.3": - version "8.3.3" - resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.3.tgz#c6a60686d953dbd1b1d45e66f4ecdbd5d471b4d0" - integrity sha512-0LbEEx1zxrYB3pgpd1M5lEhLcXjKJnYghvhTRgaBeUivLHMDM1TzF3IJ6hXU2+8uA4Xz+5BA63mtZo5DjVT8iA== +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== "@types/wrap-ansi@^3.0.0": version "3.0.0" @@ -1952,10 +1952,10 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@xmldom/xmldom@^0.7.5": - version "0.7.5" - resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" - integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== +"@xmldom/xmldom@^0.8.0": + version "0.8.0" + resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.0.tgz#9f83fd9b3506c9603baad67e44eb6e6ee8eee0ce" + integrity sha512-7wVnF+rKrVDEo1xjzkkidTG0grclaVnX0vKa0z9JSXcEdtftUJjvU33jLGg6SHyvs3eeqEsI7jZ6NxYfRypEEg== "@yarnpkg/lockfile@^1.1.0": version "1.1.0" @@ -2267,9 +2267,9 @@ astral-regex@^2.0.0: integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async@^3.2.0: - version "3.2.2" - resolved "https://registry.npmjs.org/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd" - integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g== + version "3.2.3" + resolved "https://registry.npmjs.org/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" + integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== asynckit@^0.4.0: version "0.4.0" @@ -2301,9 +2301,9 @@ aws-sdk-mock@^5.5.1: traverse "^0.6.6" aws-sdk@^2.596.0, aws-sdk@^2.848.0, aws-sdk@^2.928.0, aws-sdk@^2.979.0: - version "2.1050.0" - resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1050.0.tgz#172e80839a3c1bed82e7c42db2fbe7d46fbb90ca" - integrity sha512-xXY3wAZQyh/d6vk5oClyB3ViFENc1OOrsB/HUu/g+wnMzMLp+ea+OpZwRM5+g90mAiJ1eLOxje0Sgnbe7fP2oA== + version "2.1055.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1055.0.tgz#07beb86650d5a313f7c899807c51b12b5e2f4117" + integrity sha512-99drH3mvXakw9we8Rs2cDQmi2pS7PVAC9pvTlB7lHPUwLYftMlko5cFMceZxvTHeyLkdvg98iNIHI3hbnzitoQ== dependencies: buffer "4.9.2" events "1.1.1" @@ -2598,9 +2598,9 @@ camelcase@^6.2.0, camelcase@^6.2.1, camelcase@^6.3.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001286: - version "1.0.30001296" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz#d99f0f3bee66544800b93d261c4be55a35f1cec8" - integrity sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q== + version "1.0.30001299" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz#d753bf6444ed401eb503cbbe17aa3e1451b5a68c" + integrity sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw== case@1.6.3, case@^1.6.3: version "1.6.3" @@ -2612,32 +2612,32 @@ caseless@~0.12.0: resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -cdk-generate-synthetic-examples@^0.1.1: - version "0.1.1" - resolved "https://registry.npmjs.org/cdk-generate-synthetic-examples/-/cdk-generate-synthetic-examples-0.1.1.tgz#0e93c4ddda60920017d6943d097389f5816a9470" - integrity sha512-12Ion5PE2Gox2IR25c1PNv7usZlyO7679KE72esyoVcrznja/DPVJw+zS0B/y2VccnVMLamwanBZqE9vRVXexw== +cdk-generate-synthetic-examples@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/cdk-generate-synthetic-examples/-/cdk-generate-synthetic-examples-0.1.2.tgz#356e9a96c8f5f681245847d15407b6fc48038cd7" + integrity sha512-vHM+U/JIBU/xiC0/Joo8UOkcqPdN3vBMsToib/ekD3nraDgeFeKZ2I0DAxetjk+9Ned34NBA+u8malVxwVuiTw== dependencies: - "@jsii/spec" "^1.50.0" + "@jsii/spec" "^1.52.1" fs-extra "^10.0.0" - jsii "^1.50.0" - jsii-reflect "^1.50.0" - jsii-rosetta "^1.50.0" - yargs "^17.3.0" + jsii "^1.52.1" + jsii-reflect "^1.52.1" + jsii-rosetta "^1.52.1" + yargs "^17.3.1" -cdk8s-plus-21@^1.0.0-beta.72: - version "1.0.0-beta.72" - resolved "https://registry.npmjs.org/cdk8s-plus-21/-/cdk8s-plus-21-1.0.0-beta.72.tgz#e1f346a1ceddbda2b5bb273caf596943869c7a35" - integrity sha512-txhDpGERstsKZFVN1FvgmzUWfYwpwxHvWNrkPK+ZgRqkozFUvmry4Txk1PezVdGcVmffKEpmaSf7W0yIDkQ61w== +cdk8s-plus-21@^1.0.0-beta.73: + version "1.0.0-beta.73" + resolved "https://registry.npmjs.org/cdk8s-plus-21/-/cdk8s-plus-21-1.0.0-beta.73.tgz#72e611ad1d8a168e7b62b07e6cc979b4e73dddc8" + integrity sha512-a7RtYlNZwiSzknvhC2+9LHpLUxCMIrfgsRaIjLgxDPgNImCdpPgvlVCdMXuntvXWHgTeTSh+PwSau0mO2qphnQ== dependencies: minimatch "^3.0.4" -cdk8s@^1.3.26: - version "1.3.26" - resolved "https://registry.npmjs.org/cdk8s/-/cdk8s-1.3.26.tgz#e0a0cfb10aa17226b299219adba03d4bd6102365" - integrity sha512-VuAf6FsYnosac/8p1wZrmZQQ/Sb7WiIgCz8VWN4acsSOFWFAHQLePMrkq0VMKbRd2H+KjXhIkOJ+kvLQ9QRX8A== +cdk8s@^1.3.32: + version "1.3.32" + resolved "https://registry.npmjs.org/cdk8s/-/cdk8s-1.3.32.tgz#bbb21a249827ba48b0521f25121d47fd8ec1a548" + integrity sha512-E1BM3DFEdkrwHaiBXBoil7fVN882PXwE12RLr/Czou18wUdcjb770VS3+MhJuRrqS4RDCY6bmsGr4GYLyjM7CA== dependencies: fast-json-patch "^2.2.1" - follow-redirects "^1.14.6" + follow-redirects "^1.14.7" yaml "2.0.0-7" chalk@^2.0.0, chalk@^2.4.2: @@ -2797,15 +2797,10 @@ co@^4.6.0: resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -codemaker@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.50.0.tgz#4bede777037eb1db95b08814738a4013918ba783" - integrity sha512-6PqfJzSjboI02C+mlDz5kih0ev0R7rv55a7dRFXVnC2DX9qZjpfRsJ68ODSTEU/tlG8f+m3FC2FCPq7IUFCQlQ== +codemaker@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/codemaker/-/codemaker-1.52.1.tgz#11e1c8382ade05af7785d2a98d32f584c27e8f9d" + integrity sha512-yCEUas8OlyuAu3NZ9mKopBlEnwudUrxUokSjQkw3Zk4hYkgtYJEtu1ZXuPlXtTKQYCqTPEPsUiHayTeC1qZjUA== dependencies: camelcase "^6.2.1" decamelize "^5.0.1" @@ -2840,7 +2835,7 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colors@1.4.0, colors@^1.4.0: +colors@1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -2927,9 +2922,9 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constructs@^3.3.69: - version "3.3.180" - resolved "https://registry.npmjs.org/constructs/-/constructs-3.3.180.tgz#39de7df78ab3ee607d38a5ca6a4258ec41f0e6ae" - integrity sha512-1tbMkn0txFf/bLYio+tt0dhZYW2yEFjuTDBTftNjJPE9N28hWHPD+Ux6Lj9MqHYupH6mKA9TZ0fitpNqlWK9jw== + version "3.3.186" + resolved "https://registry.npmjs.org/constructs/-/constructs-3.3.186.tgz#8a2deca58191d4a47ce564d82800c78221a0d064" + integrity sha512-QgX306tEq7aUo2CnJlhlYyHgBbuwHdmSxFFg42qR2AvOr8f9tHZA4326OlfsiPrTu0I5JmcER7fGsT2K9vIhVw== conventional-changelog-angular@^5.0.12: version "5.0.13" @@ -3574,9 +3569,9 @@ ecc-jsbn@~0.1.1: safer-buffer "^2.1.0" electron-to-chromium@^1.4.17: - version "1.4.35" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.35.tgz#69aabb73d7030733e71c1e970ec16f5ceefbaea4" - integrity sha512-wzTOMh6HGFWeALMI3bif0mzgRrVGyP1BdFRx7IvWukFrSC5QVQELENuy+Fm2dCrAdQH9T3nuqr07n94nPDFBWA== + version "1.4.43" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.43.tgz#665c0cd8d5e7cce0ba78d90a514c8c813ca3bdbe" + integrity sha512-PO3kEfcxPrti/4STbXvCkNIF4fgWvCKl2508e6UI7KomCDffpIfeBZLXsh5DK/XGsjUw3kwq6WEsi0MJTlGAdg== emittery@^0.8.1: version "0.8.1" @@ -3731,119 +3726,119 @@ es6-weak-map@^2.0.3: es6-iterator "^2.0.3" es6-symbol "^3.1.1" -esbuild-android-arm64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.10.tgz#c854db57dc2d4df6f4f62185ca812f26a132bf1e" - integrity sha512-vzkTafHKoiMX4uIN1kBnE/HXYLpNT95EgGanVk6DHGeYgDolU0NBxjO7yZpq4ZGFPOx8384eAdDrBYhO11TAlQ== - -esbuild-darwin-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.10.tgz#c44fab6b8bfc83e5d083f513e4acbff14fb82eac" - integrity sha512-DJwzFVB95ZV7C3PQbf052WqaUuuMFXJeZJ0LKdnP1w+QOU0rlbKfX0tzuhoS//rOXUj1TFIwRuRsd0FX6skR7A== - -esbuild-darwin-arm64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.10.tgz#9454b3763b36407dc395c4c3529fb5ddd4a6225f" - integrity sha512-RNaaoZDg3nsqs5z56vYCjk/VJ76npf752W0rOaCl5lO5TsgV9zecfdYgt7dtUrIx8b7APhVaNYud+tGsDOVC9g== - -esbuild-freebsd-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.10.tgz#04eef46d5d5e4152c6b5a6a12f432db0fe7c89de" - integrity sha512-10B3AzW894u6bGZZhWiJOHw1uEHb4AFbUuBdyml1Ht0vIqd+KqWW+iY/yMwQAzILr2WJZqEhbOXRkJtY8aRqOw== - -esbuild-freebsd-arm64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.10.tgz#67ca88529543ada948737c95819253ead16494a7" - integrity sha512-mSQrKB7UaWvuryBTCo9leOfY2uEUSimAvcKIaUWbk5Hth9Sg+Try+qNA/NibPgs/vHkX0KFo/Rce6RPea+P15g== - -esbuild-linux-32@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.10.tgz#8f3d5fb0b9b616d6b604da781d71767d7679f64f" - integrity sha512-lktF09JgJLZ63ANYHIPdYe339PDuVn19Q/FcGKkXWf+jSPkn5xkYzAabboNGZNUgNqSJ/vY7VrOn6UrBbJjgYA== - -esbuild-linux-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.10.tgz#c1c60a079c4709164bdd89fbb007a2edeea7c34a" - integrity sha512-K+gCQz2oLIIBI8ZM77e9sYD5/DwEpeYCrOQ2SYXx+R4OU2CT9QjJDi4/OpE7ko4AcYMlMW7qrOCuLSgAlEj4Wg== - -esbuild-linux-arm64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.10.tgz#d8f1f89190f6d8b6e06a1214aafba454e5daa990" - integrity sha512-+qocQuQvcp5wo/V+OLXxqHPc+gxHttJEvbU/xrCGE03vIMqraL4wMua8JQx0SWEnJCWP+Nhf//v8OSwz1Xr5kA== - -esbuild-linux-arm@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.10.tgz#43192a00019a4553fb44e67f628fff0f560f16c2" - integrity sha512-BYa60dZ/KPmNKYxtHa3LSEdfKWHcm/RzP0MjB4AeBPhjS0D6/okhaBesZIY9kVIGDyeenKsJNOmnVt4+dhNnvQ== - -esbuild-linux-mips64le@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.10.tgz#f57bb8b2f1a3063cc91cfd787c8a9130cf863c16" - integrity sha512-nmUd2xoBXpGo4NJCEWoaBj+n4EtDoLEvEYc8Z3aSJrY0Oa6s04czD1flmhd0I/d6QEU8b7GQ9U0g/rtBfhtxBg== - -esbuild-linux-ppc64le@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.10.tgz#becd965bfe3425d41e026f1c4678b393127fecbd" - integrity sha512-vsOWZjm0rZix7HSmqwPph9arRVCyPtUpcURdayQDuIhMG2/UxJxpbdRaa//w4zYqcJzAWwuyH2PAlyy0ZNuxqQ== - -esbuild-linux-s390x@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.10.tgz#cc4228ac842febc48b84757814bed964a619be62" - integrity sha512-knArKKZm0ypIYWOWyOT7+accVwbVV1LZnl2FWWy05u9Tyv5oqJ2F5+X2Vqe/gqd61enJXQWqoufXopvG3zULOg== - -esbuild-netbsd-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.10.tgz#6ec50d9e4547a7579f447307b19f66bbedfd868b" - integrity sha512-6Gg8neVcLeyq0yt9bZpReb8ntZ8LBEjthxrcYWVrBElcltnDjIy1hrzsujt0+sC2rL+TlSsE9dzgyuvlDdPp2w== - -esbuild-openbsd-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.10.tgz#925ac3d2326cc219d514e1ca806e80e5143aa043" - integrity sha512-9rkHZzp10zI90CfKbFrwmQjqZaeDmyQ6s9/hvCwRkbOCHuto6RvMYH9ghQpcr5cUxD5OQIA+sHXi0zokRNXjcg== - -esbuild-sunos-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.10.tgz#8d3576d8cac5c4f9f2a84be81b9078d424dbc739" - integrity sha512-mEU+pqkhkhbwpJj5DiN3vL0GUFR/yrL3qj8ER1amIVyRibKbj02VM1QaIuk1sy5DRVIKiFXXgCaHvH3RNWCHIw== - -esbuild-windows-32@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.10.tgz#8a67fca4cb594a340566d66eef3f568f65057a48" - integrity sha512-Z5DieUL1N6s78dOSdL95KWf8Y89RtPGxIoMF+LEy8ChDsX+pZpz6uAVCn+YaWpqQXO+2TnrcbgBIoprq2Mco1g== - -esbuild-windows-64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.10.tgz#5e6d7c475ff6a71ad0aa4046894364e6c40a9249" - integrity sha512-LE5Mm62y0Bilu7RDryBhHIX8rK3at5VwJ6IGM3BsASidCfOBTzqcs7Yy0/Vkq39VKeTmy9/66BAfVoZRNznoDw== - -esbuild-windows-arm64@0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.10.tgz#50ab9a83f6ccf71c272e58489ecc4d7375075f32" - integrity sha512-OJOyxDtabvcUYTc+O4dR0JMzLBz6G9+gXIHA7Oc5d5Fv1xiYa0nUeo8+W5s2e6ZkPRdIwOseYoL70rZz80S5BA== - -esbuild@^0.14.10: - version "0.14.10" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.10.tgz#10268d2b576b25ed6f8554553413988628a7767b" - integrity sha512-ibZb+NwFqBwHHJlpnFMtg4aNmVK+LUtYMFC9CuKs6lDCBEvCHpqCFZFEirpqt1jOugwKGx8gALNGvX56lQyfew== +esbuild-android-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.11.tgz#b8b34e35a5b43880664ac7a3fbc70243d7ed894f" + integrity sha512-6iHjgvMnC/SzDH8TefL+/3lgCjYWwAd1LixYfmz/TBPbDQlxcuSkX0yiQgcJB9k+ibZ54yjVXziIwGdlc+6WNw== + +esbuild-darwin-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.11.tgz#ba805de98c0412e50fcd0636451797da157b0625" + integrity sha512-olq84ikh6TiBcrs3FnM4eR5VPPlcJcdW8BnUz/lNoEWYifYQ+Po5DuYV1oz1CTFMw4k6bQIZl8T3yxL+ZT2uvQ== + +esbuild-darwin-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.11.tgz#4d3573e448af76ce33e16231f3d9f878542d6fe8" + integrity sha512-Jj0ieWLREPBYr/TZJrb2GFH8PVzDqiQWavo1pOFFShrcmHWDBDrlDxPzEZ67NF/Un3t6sNNmeI1TUS/fe1xARg== + +esbuild-freebsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.11.tgz#9294e6ab359ec93590ab097b0f2017de7c78ab4d" + integrity sha512-C5sT3/XIztxxz/zwDjPRHyzj/NJFOnakAanXuyfLDwhwupKPd76/PPHHyJx6Po6NI6PomgVp/zi6GRB8PfrOTA== + +esbuild-freebsd-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.11.tgz#ae3e0b09173350b66cf8321583c9a1c1fcb8bb55" + integrity sha512-y3Llu4wbs0bk4cwjsdAtVOesXb6JkdfZDLKMt+v1U3tOEPBdSu6w8796VTksJgPfqvpX22JmPLClls0h5p+L9w== + +esbuild-linux-32@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.11.tgz#ddadbc7038aa5a6b1675bb1503cf79a0cbf1229a" + integrity sha512-Cg3nVsxArjyLke9EuwictFF3Sva+UlDTwHIuIyx8qpxRYAOUTmxr2LzYrhHyTcGOleLGXUXYsnUVwKqnKAgkcg== + +esbuild-linux-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.11.tgz#d698e3ce3a231ddfeec6b5df8c546ae8883fcd88" + integrity sha512-oeR6dIrrojr8DKVrxtH3xl4eencmjsgI6kPkDCRIIFwv4p+K7ySviM85K66BN01oLjzthpUMvBVfWSJkBLeRbg== + +esbuild-linux-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.11.tgz#85faea9fa99ad355b5e3b283197a4dfd0a110fe7" + integrity sha512-+e6ZCgTFQYZlmg2OqLkg1jHLYtkNDksxWDBWNtI4XG4WxuOCUErLqfEt9qWjvzK3XBcCzHImrajkUjO+rRkbMg== + +esbuild-linux-arm@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.11.tgz#74cbcf0b8a22c8401bcbcd6ebd4cbf2baca8b7b4" + integrity sha512-vcwskfD9g0tojux/ZaTJptJQU3a7YgTYsptK1y6LQ/rJmw7U5QJvboNawqM98Ca3ToYEucfCRGbl66OTNtp6KQ== + +esbuild-linux-mips64le@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.11.tgz#490429211a3233f5cbbd8575b7758b897e42979a" + integrity sha512-Rrs99L+p54vepmXIb87xTG6ukrQv+CzrM8eoeR+r/OFL2Rg8RlyEtCeshXJ2+Q66MXZOgPJaokXJZb9snq28bw== + +esbuild-linux-ppc64le@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.11.tgz#fc79d60710213b5b98345f5b138d48245616827a" + integrity sha512-JyzziGAI0D30Vyzt0HDihp4s1IUtJ3ssV2zx9O/c+U/dhUHVP2TmlYjzCfCr2Q6mwXTeloDcLS4qkyvJtYptdQ== + +esbuild-linux-s390x@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.11.tgz#ca4b93556bbba6cc95b0644f2ee93c982165ba07" + integrity sha512-DoThrkzunZ1nfRGoDN6REwmo8ZZWHd2ztniPVIR5RMw/Il9wiWEYBahb8jnMzQaSOxBsGp0PbyJeVLTUatnlcw== + +esbuild-netbsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.11.tgz#edb340bc6653c88804cac2253e21b74258fce165" + integrity sha512-12luoRQz+6eihKYh1zjrw0CBa2aw3twIiHV/FAfjh2NEBDgJQOY4WCEUEN+Rgon7xmLh4XUxCQjnwrvf8zhACw== + +esbuild-openbsd-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.11.tgz#caeff5f946f79a60ce7bcf88871ca4c71d3476e8" + integrity sha512-l18TZDjmvwW6cDeR4fmizNoxndyDHamGOOAenwI4SOJbzlJmwfr0jUgjbaXCUuYVOA964siw+Ix+A+bhALWg8Q== + +esbuild-sunos-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.11.tgz#90ce7e1749c2958a53509b4bae7b8f7d98f276d6" + integrity sha512-bmYzDtwASBB8c+0/HVOAiE9diR7+8zLm/i3kEojUH2z0aIs6x/S4KiTuT5/0VKJ4zk69kXel1cNWlHBMkmavQg== + +esbuild-windows-32@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.11.tgz#d067f4ce15b29efba6336e6a23597120fafe49ec" + integrity sha512-J1Ys5hMid8QgdY00OBvIolXgCQn1ARhYtxPnG6ESWNTty3ashtc4+As5nTrsErnv8ZGUcWZe4WzTP/DmEVX1UQ== + +esbuild-windows-64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.11.tgz#13e86dd37a6cd61a5276fa2d271342d0f74da864" + integrity sha512-h9FmMskMuGeN/9G9+LlHPAoiQk9jlKDUn9yA0MpiGzwLa82E7r1b1u+h2a+InprbSnSLxDq/7p5YGtYVO85Mlg== + +esbuild-windows-arm64@0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.11.tgz#e8edfdf1d712085e6dc3fba18a0c225aaae32b75" + integrity sha512-dZp7Krv13KpwKklt9/1vBFBMqxEQIO6ri7Azf8C+ob4zOegpJmha2XY9VVWP/OyQ0OWk6cEeIzMJwInRZrzBUQ== + +esbuild@^0.14.11: + version "0.14.11" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.11.tgz#ac4acb78907874832afb704c3afe58ad37715c27" + integrity sha512-xZvPtVj6yecnDeFb3KjjCM6i7B5TCAQZT77kkW/CpXTMnd6VLnRPKrUB1XHI1pSq6a4Zcy3BGueQ8VljqjDGCg== optionalDependencies: - esbuild-android-arm64 "0.14.10" - esbuild-darwin-64 "0.14.10" - esbuild-darwin-arm64 "0.14.10" - esbuild-freebsd-64 "0.14.10" - esbuild-freebsd-arm64 "0.14.10" - esbuild-linux-32 "0.14.10" - esbuild-linux-64 "0.14.10" - esbuild-linux-arm "0.14.10" - esbuild-linux-arm64 "0.14.10" - esbuild-linux-mips64le "0.14.10" - esbuild-linux-ppc64le "0.14.10" - esbuild-linux-s390x "0.14.10" - esbuild-netbsd-64 "0.14.10" - esbuild-openbsd-64 "0.14.10" - esbuild-sunos-64 "0.14.10" - esbuild-windows-32 "0.14.10" - esbuild-windows-64 "0.14.10" - esbuild-windows-arm64 "0.14.10" + esbuild-android-arm64 "0.14.11" + esbuild-darwin-64 "0.14.11" + esbuild-darwin-arm64 "0.14.11" + esbuild-freebsd-64 "0.14.11" + esbuild-freebsd-arm64 "0.14.11" + esbuild-linux-32 "0.14.11" + esbuild-linux-64 "0.14.11" + esbuild-linux-arm "0.14.11" + esbuild-linux-arm64 "0.14.11" + esbuild-linux-mips64le "0.14.11" + esbuild-linux-ppc64le "0.14.11" + esbuild-linux-s390x "0.14.11" + esbuild-netbsd-64 "0.14.11" + esbuild-openbsd-64 "0.14.11" + esbuild-sunos-64 "0.14.11" + esbuild-windows-32 "0.14.11" + esbuild-windows-64 "0.14.11" + esbuild-windows-arm64 "0.14.11" escalade@^3.1.1: version "3.1.1" @@ -4200,10 +4195,10 @@ extsprintf@^1.2.0: resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -fast-check@^2.20.0: - version "2.20.0" - resolved "https://registry.npmjs.org/fast-check/-/fast-check-2.20.0.tgz#0c88d8640649e981adb501ef92f90a26dc8bd628" - integrity sha512-tFNjLyPnOUg6iimVxOtoWMJOIyybCo7B8gUGm1yv43jDCQ0hlPUn0fmna/XO/n1yPxn/dxQw3+IygPSbMDiiog== +fast-check@^2.21.0: + version "2.21.0" + resolved "https://registry.npmjs.org/fast-check/-/fast-check-2.21.0.tgz#0d2e20bc65343ee67ec0f58373358140c08a1217" + integrity sha512-hkTRytqMceXfnSwPnryIqKkxKJjfcvtVqJrWRb8tgmfyUsGajIgQqDFxCJ+As+l9VLUCcmx6XIYoXeQe2Ih0UA== dependencies: pure-rand "^5.0.0" @@ -4217,10 +4212,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1: - version "3.2.7" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.9: + version "3.2.10" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.10.tgz#2734f83baa7f43b7fd41e13bc34438f4ffe284ee" + integrity sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4367,10 +4362,10 @@ flatted@^3.1.0: resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== -follow-redirects@^1.14.0, follow-redirects@^1.14.6: - version "1.14.6" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" - integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== +follow-redirects@^1.14.0, follow-redirects@^1.14.7: + version "1.14.7" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" + integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== foreach@^2.0.5: version "2.0.5" @@ -4692,15 +4687,15 @@ globals@^13.6.0, globals@^13.9.0: type-fest "^0.20.2" globby@^11.0.2, globby@^11.0.3: - version "11.0.4" - resolved "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + version "11.1.0" + resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4, graceful-fs@^4.2.9: @@ -4796,9 +4791,9 @@ hosted-git-info@^2.1.4: integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.0.2" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + version "4.1.0" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" @@ -4904,7 +4899,7 @@ ignore@^4.0.6: resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -4928,9 +4923,9 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: resolve-from "^4.0.0" import-local@^3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" - integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== + version "3.1.0" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -5072,9 +5067,9 @@ is-ci@^2.0.0: ci-info "^2.0.0" is-core-module@^2.5.0, is-core-module@^2.8.0: - version "2.8.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== + version "2.8.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== dependencies: has "^1.0.3" @@ -5095,13 +5090,6 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -5814,7 +5802,7 @@ jest-worker@^27.4.6: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^27.3.1, jest@^27.4.7: +jest@^27.3.1, jest@^27.4.5, jest@^27.4.7: version "27.4.7" resolved "https://registry.npmjs.org/jest/-/jest-27.4.7.tgz#87f74b9026a1592f2da05b4d258e57505f28eca4" integrity sha512-8heYvsx7nV/m8m24Vk26Y87g73Ba6ueUd0MWed/NXMhSZIm62U/llVbS0PJe1SHunbyXjJ/BqG1z9bFjGUIvTg== @@ -5896,75 +5884,75 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsii-diff@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.50.0.tgz#61c9ba5d59ed17c15a45315b9b73068dd8c3adb8" - integrity sha512-hyRXf8jNoBOK5e3tsQhzQs8wiR83FmRywUNGZGtAD/s52UTAnPb/V/DH52hY6pTUa08aLZEQbqpgwooOOe94hw== +jsii-diff@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/jsii-diff/-/jsii-diff-1.52.1.tgz#cfc9b287e8a5c3c7a137cf2a50e29a7e6f405e76" + integrity sha512-bfzIJPzckF5PAncQp/aF2GDITGZarhXIIHKD9Uk7/jWuXx02Gt7Bysd7YIWIwMgIrKD0O0okzeLP/LbnQcBJ2w== dependencies: - "@jsii/check-node" "1.50.0" - "@jsii/spec" "^1.50.0" + "@jsii/check-node" "1.52.1" + "@jsii/spec" "^1.52.1" fs-extra "^9.1.0" - jsii-reflect "^1.50.0" + jsii-reflect "^1.52.1" log4js "^6.3.0" typescript "~3.9.10" yargs "^16.2.0" -jsii-pacmak@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.50.0.tgz#91a602c53695b9c4ad6b9b3e55aa45134a52bcc3" - integrity sha512-EE8sZqYumlik6LbZVKntRE169F4zE/cly74LijQWUIehvOhWafk0wZsPYwOBSZl8tYeTTrF6w4TPxt1+7e3JaQ== +jsii-pacmak@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/jsii-pacmak/-/jsii-pacmak-1.52.1.tgz#c904691969716f9aada1dbd254661dc2bec3d24e" + integrity sha512-6bIGCtfu8UAr3dmddbyqGGyFyz4TOr5aC1eo4Cqwl23v/elkzxYV8TFCra9HksVxDi6UtTYJuypnExb4gsOcgQ== dependencies: - "@jsii/check-node" "1.50.0" - "@jsii/spec" "^1.50.0" + "@jsii/check-node" "1.52.1" + "@jsii/spec" "^1.52.1" clone "^2.1.2" - codemaker "^1.50.0" + codemaker "^1.52.1" commonmark "^0.30.0" escape-string-regexp "^4.0.0" fs-extra "^9.1.0" - jsii-reflect "^1.50.0" - jsii-rosetta "^1.50.0" + jsii-reflect "^1.52.1" + jsii-rosetta "^1.52.1" semver "^7.3.5" spdx-license-list "^6.4.0" xmlbuilder "^15.1.1" yargs "^16.2.0" -jsii-reflect@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.50.0.tgz#51ddf22cd4dea45f494edb637506009efa988fb0" - integrity sha512-SPMDhrCkkCLPQR6P6qX8eW9v6UuGxyD061021WQZM/F+GsJZA+puQFJX8Jq2swv08O4iSVlVtE9iPQ+UhuNLoQ== +jsii-reflect@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/jsii-reflect/-/jsii-reflect-1.52.1.tgz#b634f374961e72259dd79f198aa7e6ec45a3bbb2" + integrity sha512-OsTquiUJkgUu5jlK2VeshLFP9mBd1NU7vhHvcJZ+0xc/u2byfzPT0Irj2o6XLp30Vx/+uGGK6Nf6KyKtmUe82w== dependencies: - "@jsii/check-node" "1.50.0" - "@jsii/spec" "^1.50.0" - colors "^1.4.0" + "@jsii/check-node" "1.52.1" + "@jsii/spec" "^1.52.1" + colors "1.4.0" fs-extra "^9.1.0" - oo-ascii-tree "^1.50.0" + oo-ascii-tree "^1.52.1" yargs "^16.2.0" -jsii-rosetta@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.50.0.tgz#2a0f13bffcd6f599032742b01065c612bc212cb3" - integrity sha512-CuOu7lT24WVYrWI5Uynymdvgp7wwLsd2CtOV9Fs1Lv5RvnOMZ2VGUx2fCDp/oCA5uRQdesknnuj7xBREX/edKg== +jsii-rosetta@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/jsii-rosetta/-/jsii-rosetta-1.52.1.tgz#1a47b77796630b4a417cf1e9f51a5a2cba460b67" + integrity sha512-iFpupZWQusVYGHaUPooaO6xVAtRp+o1EOMBS2FcJBZcWGbB8fRG3zzpeMSkoqu/Pjqtu7boh45V90CXtSmVfMQ== dependencies: - "@jsii/check-node" "1.50.0" - "@jsii/spec" "1.50.0" - "@xmldom/xmldom" "^0.7.5" + "@jsii/check-node" "1.52.1" + "@jsii/spec" "1.52.1" + "@xmldom/xmldom" "^0.8.0" commonmark "^0.30.0" fs-extra "^9.1.0" - jsii "1.50.0" + jsii "1.52.1" sort-json "^2.0.0" typescript "~3.9.10" workerpool "^6.1.5" yargs "^16.2.0" -jsii@1.50.0, jsii@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/jsii/-/jsii-1.50.0.tgz#585232437fcf0a4edaa3c329de2d1c7d05765a3d" - integrity sha512-7a9QXBe/MvOTGFpr5ASetxqrOd8Y6sdZo7Ts2UNJRQQWA+YS/hVpOuemnvdUImdo5u659gqdcXLsKy48QXiC/Q== +jsii@1.52.1, jsii@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/jsii/-/jsii-1.52.1.tgz#cfee7359ce9a6d877eadd2b5a0dff14f618f7a55" + integrity sha512-kILHStPX3xeADtB/2Wda56Mzz/6KUw8xNr/k+dp84qn9YlZA81cW85tKK5biYCy/XAh5IPsWIZVFRqR8CSPMMw== dependencies: - "@jsii/check-node" "1.50.0" - "@jsii/spec" "^1.50.0" + "@jsii/check-node" "1.52.1" + "@jsii/spec" "^1.52.1" case "^1.6.3" - colors "^1.4.0" + colors "1.4.0" deep-equal "^2.0.5" fs-extra "^9.1.0" log4js "^6.3.0" @@ -6589,7 +6577,7 @@ merge-stream@^2.0.0: resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -6856,10 +6844,10 @@ nise@^5.1.0: just-extend "^4.0.2" path-to-regexp "^1.7.0" -nock@^13.2.1: - version "13.2.1" - resolved "https://registry.npmjs.org/nock/-/nock-13.2.1.tgz#fcf5bdb9bb9f0554a84c25d3333166c0ffd80858" - integrity sha512-CoHAabbqq/xZEknubuyQMjq6Lfi5b7RtK6SoNK6m40lebGp3yiMagWtIoYaw2s9sISD7wPuCfwFpivVHX/35RA== +nock@^13.2.2: + version "13.2.2" + resolved "https://registry.npmjs.org/nock/-/nock-13.2.2.tgz#29a6942250278209c2b3e7a38310f703581b21fa" + integrity sha512-PcBHuvl9i6zfaJ50A7LS55oU+nFLv8htXIhffJO+FxyfibdZ4jEvd9kTuvkrJireBFIGMZ+oUIRpMK5gU9h//g== dependencies: debug "^4.1.0" json-stringify-safe "^5.0.1" @@ -7085,11 +7073,6 @@ null-check@^1.0.0: resolved "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -7203,10 +7186,10 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -oo-ascii-tree@^1.50.0: - version "1.50.0" - resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.50.0.tgz#52fa4e4081f050f349459bc72630f5f50dbb2d97" - integrity sha512-943KZJW94gBh+naWsXvw4ISsHnlEXXkx5Yf8wA6NLOeLlY2Xj7tN/W+FhKNTlI9Y99Vz0NQQP+8o9Q05I8Ld9Q== +oo-ascii-tree@^1.52.1: + version "1.52.1" + resolved "https://registry.npmjs.org/oo-ascii-tree/-/oo-ascii-tree-1.52.1.tgz#cdd0d6db64a3fac734cbe98fbb8c65ad0fd04853" + integrity sha512-hcQSkW/WkZFWqK878X+Bo8vD2Axo9FBQBGeTLANgWOay7IVFUvLmqbFUyfovzD+/L4ak1n/BdsWfSL/0a3NT2w== open@^7.4.2: version "7.4.2" @@ -7773,16 +7756,16 @@ q@^1.5.1: integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= qs@^6.9.4: - version "6.10.2" - resolved "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz#c1431bea37fc5b24c5bdbafa20f16bdf2a4b9ffe" - integrity sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw== + version "6.10.3" + resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== dependencies: side-channel "^1.0.4" qs@~6.5.2: - version "6.5.2" - resolved "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + version "6.5.3" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== query-string@^6.13.8: version "6.14.1" @@ -8465,9 +8448,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + version "1.17.0" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -8541,7 +8524,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@*, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8550,15 +8533,6 @@ string-width@*, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, strin is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - string.prototype.repeat@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz#aba36de08dcee6a5a337d49b2ea1da1b28fc0ecf" @@ -9066,17 +9040,17 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript-json-schema@^0.52.0: - version "0.52.0" - resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.52.0.tgz#954560ec90e5486e8f7a5b7706ec59286a708e29" - integrity sha512-3ZdHzx116gZ+D9LmMl5/+d1G3Rpt8baWngKzepYWHnXbAa8Winv64CmFRqLlMKneE1c40yugYDFcWdyX1FjGzQ== +typescript-json-schema@^0.53.0: + version "0.53.0" + resolved "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.53.0.tgz#ac5b89e4b0af55be422f475a041360e0556f88ea" + integrity sha512-BcFxC9nipQQOXxrBGI/jOWU31BwzVh6vqJR008G8VHKJtQ8YrZX6veriXfTK1l+L0/ff0yKl3mZigMLA6ZqkHg== dependencies: "@types/json-schema" "^7.0.9" "@types/node" "^16.9.2" glob "^7.1.7" safe-stable-stringify "^2.2.0" ts-node "^10.2.1" - typescript "~4.4.4" + typescript "~4.5.0" yargs "^17.1.1" typescript@~3.8.3: @@ -9089,10 +9063,10 @@ typescript@~3.9.10: resolved "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== -typescript@~4.4.4: - version "4.4.4" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c" - integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA== +typescript@~4.5.0: + version "4.5.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" + integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -9223,9 +9197,9 @@ v8-compile-cache@^2.0.3: integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^8.1.0: - version "8.1.0" - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" - integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + version "8.1.1" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" @@ -9631,7 +9605,7 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.1.1, yargs@^17.3.0: +yargs@^17.1.1, yargs@^17.3.1: version "17.3.1" resolved "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==