diff --git a/packages/@aws-cdk/aws-cloudfront/package.json b/packages/@aws-cdk/aws-cloudfront/package.json index 3383c1e6e7e02..02aba194d2c21 100644 --- a/packages/@aws-cdk/aws-cloudfront/package.json +++ b/packages/@aws-cdk/aws-cloudfront/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudtrail/package.json b/packages/@aws-cdk/aws-cloudtrail/package.json index 1f1f3d2a7d703..fcdebbfea919f 100644 --- a/packages/@aws-cdk/aws-cloudtrail/package.json +++ b/packages/@aws-cdk/aws-cloudtrail/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts index 1ff3107932eb9..41f9ecafc04e6 100644 --- a/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts +++ b/packages/@aws-cdk/aws-cloudwatch/lib/alarm.ts @@ -42,6 +42,7 @@ export enum ComparisonOperator { GREATER_THAN_THRESHOLD = 'GreaterThanThreshold', LESS_THAN_THRESHOLD = 'LessThanThreshold', LESS_THAN_OR_EQUAL_TO_THRESHOLD = 'LessThanOrEqualToThreshold', + LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD = 'LessThanLowerOrGreaterThanUpperThreshold', } const OPERATOR_SYMBOLS: {[key: string]: string} = { diff --git a/packages/@aws-cdk/aws-cloudwatch/package.json b/packages/@aws-cdk/aws-cloudwatch/package.json index 3a8c56165c82e..7c27985c54d12 100644 --- a/packages/@aws-cdk/aws-cloudwatch/package.json +++ b/packages/@aws-cdk/aws-cloudwatch/package.json @@ -131,6 +131,7 @@ "docs-public-apis:@aws-cdk/aws-cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD", "docs-public-apis:@aws-cdk/aws-cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD", "docs-public-apis:@aws-cdk/aws-cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD", + "docs-public-apis:@aws-cdk/aws-cloudwatch.ComparisonOperator.LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD", "docs-public-apis:@aws-cdk/aws-cloudwatch.PeriodOverride", "docs-public-apis:@aws-cdk/aws-cloudwatch.PeriodOverride.AUTO", "docs-public-apis:@aws-cdk/aws-cloudwatch.PeriodOverride.INHERIT", diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 5452f2080d5fe..0689d8f6daa5b 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -70,7 +70,7 @@ "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index 9efae1b9217fb..e7f41b2f8ddca 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -70,7 +70,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/ecs/deploy-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/ecs/deploy-action.ts index 245764f12bb56..c7bc50dccf5c8 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/ecs/deploy-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/ecs/deploy-action.ts @@ -39,7 +39,7 @@ export interface EcsDeployActionProps extends codepipeline.CommonAwsActionProps /** * The ECS Service to deploy. */ - readonly service: ecs.BaseService; + readonly service: ecs.IBaseService; } /** diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/ecs/test.ecs-deploy-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/ecs/test.ecs-deploy-action.ts index 89902677ed82d..dfa0a546cbd8c 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/ecs/test.ecs-deploy-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/ecs/test.ecs-deploy-action.ts @@ -1,6 +1,8 @@ +import { expect, haveResourceLike } from '@aws-cdk/assert'; import * as codepipeline from '@aws-cdk/aws-codepipeline'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; +import * as s3 from '@aws-cdk/aws-s3'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; import * as cpactions from '../../lib'; @@ -80,6 +82,71 @@ export = { test.done(); }, + + 'can be created by existing service'(test: Test) { + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const service = ecs.FargateService.fromFargateServiceAttributes(stack, 'FargateService', { + serviceName: 'service-name', + cluster: ecs.Cluster.fromClusterAttributes(stack, 'Cluster', { + vpc, + securityGroups: [], + clusterName: 'cluster-name', + }), + }); + const artifact = new codepipeline.Artifact('Artifact'); + const bucket = new s3.Bucket(stack, 'PipelineBucket', { + versioned: true, + removalPolicy: cdk.RemovalPolicy.DESTROY, + }); + const source = new cpactions.S3SourceAction({ + actionName: 'Source', + output: artifact, + bucket, + bucketKey: 'key', + }); + const action = new cpactions.EcsDeployAction({ + actionName: 'ECS', + service, + imageFile: artifact.atPath('imageFile.json'), + }); + new codepipeline.Pipeline(stack, 'Pipeline', { + stages: [ + { + stageName: 'Source', + actions: [source], + }, + { + stageName: 'Deploy', + actions: [action], + } + ], + }); + + expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', { + Stages: [ + {}, + { + Actions: [ + { + Name: 'ECS', + ActionTypeId: { + Category: "Deploy", + Provider: "ECS" + }, + Configuration: { + ClusterName: "cluster-name", + ServiceName: "service-name", + FileName: "imageFile.json" + } + } + ] + } + ] + })); + + test.done(); + }, }, }; diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index c0c4ba9c086b1..dd1c9bd4d8aaf 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts index 83d3709d1e9a7..a833471b733ef 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts @@ -1,7 +1,7 @@ import { expect, haveResource, ResourcePart, SynthUtils } from '@aws-cdk/assert'; import * as appscaling from '@aws-cdk/aws-applicationautoscaling'; import * as iam from '@aws-cdk/aws-iam'; -import { App, CfnDeletionPolicy, ConstructNode, RemovalPolicy, Stack, Tag } from '@aws-cdk/core'; +import { App, CfnDeletionPolicy, ConstructNode, Duration, RemovalPolicy, Stack, Tag } from '@aws-cdk/core'; import { Test } from 'nodeunit'; import { Attribute, @@ -1142,7 +1142,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricConsumedReadCapacityUnits()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'ConsumedReadCapacityUnits', @@ -1161,7 +1161,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricConsumedWriteCapacityUnits()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'ConsumedWriteCapacityUnits', @@ -1180,7 +1180,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricSystemErrors()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'SystemErrors', @@ -1199,7 +1199,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricUserErrors()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'UserErrors', @@ -1218,7 +1218,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricConditionalCheckFailedRequests()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'ConditionalCheckFailedRequests', @@ -1237,7 +1237,7 @@ export = { // THEN test.deepEqual(stack.resolve(table.metricSuccessfulRequestLatency()), { - period: { amount: 5, unit: { label: 'minutes', inSeconds: 60 } }, + period: Duration.minutes(5), dimensions: { TableName: { Ref: 'TableCD117FA1' } }, namespace: 'AWS/DynamoDB', metricName: 'SuccessfulRequestLatency', diff --git a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts index c83c54b03f379..dd51713f7937c 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts @@ -22,6 +22,13 @@ export interface IService extends IResource { * @attribute */ readonly serviceArn: string; + + /** + * The name of the service. + * + * @attribute + */ + readonly serviceName: string; } /** @@ -245,11 +252,21 @@ class NetworkListenerConfig extends ListenerConfig { } } +/** + * The interface for BaseService. + */ +export interface IBaseService extends IService { + /** + * The cluster that hosts the service. + */ + readonly cluster: ICluster; +} + /** * The base class for Ec2Service and FargateService services. */ export abstract class BaseService extends Resource - implements IService, elbv2.IApplicationLoadBalancerTarget, elbv2.INetworkLoadBalancerTarget, elb.ILoadBalancerTarget { + implements IBaseService, elbv2.IApplicationLoadBalancerTarget, elbv2.INetworkLoadBalancerTarget, elb.ILoadBalancerTarget { /** * The security groups which manage the allowed network traffic for the service. diff --git a/packages/@aws-cdk/aws-ecs/lib/base/from-service-attributes.ts b/packages/@aws-cdk/aws-ecs/lib/base/from-service-attributes.ts new file mode 100644 index 0000000000000..9128c00b0430d --- /dev/null +++ b/packages/@aws-cdk/aws-ecs/lib/base/from-service-attributes.ts @@ -0,0 +1,57 @@ +import { Construct, Resource, Stack } from '@aws-cdk/core'; +import { IBaseService } from '../base/base-service'; +import { ICluster } from '../cluster'; + +/** + * The properties to import from the service. + */ +export interface ServiceAttributes { + /** + * The cluster that hosts the service. + */ + readonly cluster: ICluster; + + /** + * The service ARN. + * + * @default - either this, or {@link serviceName}, is required + */ + readonly serviceArn?: string; + + /** + * The name of the service. + * + * @default - either this, or {@link serviceArn}, is required + */ + readonly serviceName?: string; +} + +export function fromServiceAtrributes(scope: Construct, id: string, attrs: ServiceAttributes): IBaseService { + if ((attrs.serviceArn && attrs.serviceName) || (!attrs.serviceArn && !attrs.serviceName)) { + throw new Error('You can only specify either serviceArn or serviceName.'); + } + + const stack = Stack.of(scope); + let name: string; + let arn: string; + if (attrs.serviceName) { + name = attrs.serviceName as string; + arn = stack.formatArn({ + partition: stack.partition, + service: 'ecs', + region: stack.region, + account: stack.account, + resource: 'service', + resourceName: name, + }); + } else { + arn = attrs.serviceArn as string; + name = stack.parseArn(arn).resourceName as string; + } + class Import extends Resource implements IBaseService { + public readonly serviceArn = arn; + public readonly serviceName = name; + public readonly cluster = attrs.cluster; + } + return new Import(scope, id); +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts index 13877c0785126..64367f32d54aa 100644 --- a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts @@ -1,7 +1,9 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import { Construct, Lazy, Resource, Stack } from '@aws-cdk/core'; -import { BaseService, BaseServiceOptions, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { BaseService, BaseServiceOptions, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { fromServiceAtrributes } from '../base/from-service-attributes'; import { NetworkMode, TaskDefinition } from '../base/task-definition'; +import { ICluster } from '../cluster'; import { CfnService } from '../ecs.generated'; import { PlacementConstraint, PlacementStrategy } from '../placement'; @@ -87,6 +89,30 @@ export interface IEc2Service extends IService { } +/** + * The properties to import from the service using the EC2 launch type. + */ +export interface Ec2ServiceAttributes { + /** + * The cluster that hosts the service. + */ + readonly cluster: ICluster; + + /** + * The service ARN. + * + * @default - either this, or {@link serviceName}, is required + */ + readonly serviceArn?: string; + + /** + * The name of the service. + * + * @default - either this, or {@link serviceArn}, is required + */ + readonly serviceName?: string; +} + /** * This creates a service using the EC2 launch type on an ECS cluster. * @@ -100,10 +126,18 @@ export class Ec2Service extends BaseService implements IEc2Service { public static fromEc2ServiceArn(scope: Construct, id: string, ec2ServiceArn: string): IEc2Service { class Import extends Resource implements IEc2Service { public readonly serviceArn = ec2ServiceArn; + public readonly serviceName = Stack.of(scope).parseArn(ec2ServiceArn).resourceName as string; } return new Import(scope, id); } + /** + * Imports from the specified service attrributes. + */ + public static fromEc2ServiceAttributes(scope: Construct, id: string, attrs: Ec2ServiceAttributes): IBaseService { + return fromServiceAtrributes(scope, id, attrs); + } + private readonly constraints: CfnService.PlacementConstraintProperty[]; private readonly strategies: CfnService.PlacementStrategyProperty[]; private readonly daemon: boolean; diff --git a/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts b/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts index d2c064df93d6f..f8b741a584604 100644 --- a/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/fargate/fargate-service.ts @@ -1,7 +1,9 @@ import * as ec2 from '@aws-cdk/aws-ec2'; import * as cdk from '@aws-cdk/core'; -import { BaseService, BaseServiceOptions, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { BaseService, BaseServiceOptions, IBaseService, IService, LaunchType, PropagatedTagSource } from '../base/base-service'; +import { fromServiceAtrributes } from '../base/from-service-attributes'; import { TaskDefinition } from '../base/task-definition'; +import { ICluster } from '../cluster'; /** * The properties for defining a service using the Fargate launch type. @@ -65,6 +67,30 @@ export interface IFargateService extends IService { } +/** + * The properties to import from the service using the Fargate launch type. + */ +export interface FargateServiceAttributes { + /** + * The cluster that hosts the service. + */ + readonly cluster: ICluster; + + /** + * The service ARN. + * + * @default - either this, or {@link serviceName}, is required + */ + readonly serviceArn?: string; + + /** + * The name of the service. + * + * @default - either this, or {@link serviceArn}, is required + */ + readonly serviceName?: string; +} + /** * This creates a service using the Fargate launch type on an ECS cluster. * @@ -73,15 +99,23 @@ export interface IFargateService extends IService { export class FargateService extends BaseService implements IFargateService { /** - * Import a task definition from the specified task definition ARN. + * Imports from the specified service ARN. */ public static fromFargateServiceArn(scope: cdk.Construct, id: string, fargateServiceArn: string): IFargateService { class Import extends cdk.Resource implements IFargateService { public readonly serviceArn = fargateServiceArn; + public readonly serviceName = cdk.Stack.of(scope).parseArn(fargateServiceArn).resourceName as string; } return new Import(scope, id); } + /** + * Imports from the specified service attrributes. + */ + public static fromFargateServiceAttributes(scope: cdk.Construct, id: string, attrs: FargateServiceAttributes): IBaseService { + return fromServiceAtrributes(scope, id, attrs); + } + /** * Constructs a new instance of the FargateService class. */ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts index 2cc7349ac6545..61582bfaa8928 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts @@ -1936,5 +1936,74 @@ export = { }); test.done(); - } + }, + + 'When import an EC2 Service': { + 'with serviceArn'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + // WHEN + const service = ecs.Ec2Service.fromEc2ServiceAttributes(stack, 'EcsService', { + serviceArn: 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service', + cluster, + }); + + // THEN + test.equal(service.serviceArn, 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service'); + test.equal(service.serviceName, 'my-http-service'); + + test.done(); + }, + + 'with serviceName'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const pseudo = new cdk.ScopedAws(stack); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + // WHEN + const service = ecs.Ec2Service.fromEc2ServiceAttributes(stack, 'EcsService', { + serviceName: 'my-http-service', + cluster, + }); + + // THEN + test.deepEqual(stack.resolve(service.serviceArn), stack.resolve(`arn:${pseudo.partition}:ecs:${pseudo.region}:${pseudo.accountId}:service/my-http-service`)); + test.equal(service.serviceName, 'my-http-service'); + + test.done(); + }, + + 'throws an exception if both serviceArn and serviceName were provided for fromEc2ServiceAttributes'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + test.throws(() => { + ecs.Ec2Service.fromEc2ServiceAttributes(stack, 'EcsService', { + serviceArn: 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service', + serviceName: 'my-http-service', + cluster, + }); + }, /only specify either serviceArn or serviceName/); + + test.done(); + }, + + 'throws an exception if neither serviceArn nor serviceName were provided for fromEc2ServiceAttributes'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + test.throws(() => { + ecs.Ec2Service.fromEc2ServiceAttributes(stack, 'EcsService', { + cluster, + }); + }, /only specify either serviceArn or serviceName/); + + test.done(); + }, + }, }; diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts index d953b16d78ed7..b798ead19f96f 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts @@ -1487,5 +1487,74 @@ export = { }); test.done(); - } + }, + + 'When import a Fargate Service': { + 'with serviceArn'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + // WHEN + const service = ecs.FargateService.fromFargateServiceAttributes(stack, 'EcsService', { + serviceArn: 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service', + cluster, + }); + + // THEN + test.equal(service.serviceArn, 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service'); + test.equal(service.serviceName, 'my-http-service'); + + test.done(); + }, + + 'with serviceName'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const pseudo = new cdk.ScopedAws(stack); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + // WHEN + const service = ecs.FargateService.fromFargateServiceAttributes(stack, 'EcsService', { + serviceName: 'my-http-service', + cluster, + }); + + // THEN + test.deepEqual(stack.resolve(service.serviceArn), stack.resolve(`arn:${pseudo.partition}:ecs:${pseudo.region}:${pseudo.accountId}:service/my-http-service`)); + test.equal(service.serviceName, 'my-http-service'); + + test.done(); + }, + + 'throws an exception if both serviceArn and serviceName were provided for fromEc2ServiceAttributes'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + test.throws(() => { + ecs.FargateService.fromFargateServiceAttributes(stack, 'EcsService', { + serviceArn: 'arn:aws:ecs:us-west-2:123456789012:service/my-http-service', + serviceName: 'my-http-service', + cluster, + }); + }, /only specify either serviceArn or serviceName/); + + test.done(); + }, + + 'throws an exception if neither serviceArn nor serviceName were provided for fromEc2ServiceAttributes'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const cluster = new ecs.Cluster(stack, 'EcsCluster'); + + test.throws(() => { + ecs.FargateService.fromFargateServiceAttributes(stack, 'EcsService', { + cluster, + }); + }, /only specify either serviceArn or serviceName/); + + test.done(); + }, + }, }; diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index cbdbe28a60e4c..462ef29a93022 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index c11e08b961e33..4eaeb0d777ef3 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -86,7 +86,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 6810859b23dd1..9bfbb0033314d 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -71,7 +71,7 @@ "@types/lodash": "^4.14.149", "@types/nodeunit": "^0.0.30", "@types/sinon": "^7.5.2", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index f4a7eb9d3e3f0..81b11125217d5 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index 5957c20066769..7327831a320ff 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -65,7 +65,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/core/lib/duration.ts b/packages/@aws-cdk/core/lib/duration.ts index 8801d6a771a1a..69152a27b5d28 100644 --- a/packages/@aws-cdk/core/lib/duration.ts +++ b/packages/@aws-cdk/core/lib/duration.ts @@ -10,6 +10,8 @@ import { Token } from "./token"; */ export class Duration { /** + * Create a Duration representing an amount of milliseconds + * * @param amount the amount of Milliseconds the `Duration` will represent. * @returns a new `Duration` representing `amount` ms. */ @@ -18,6 +20,8 @@ export class Duration { } /** + * Create a Duration representing an amount of seconds + * * @param amount the amount of Seconds the `Duration` will represent. * @returns a new `Duration` representing `amount` Seconds. */ @@ -26,6 +30,8 @@ export class Duration { } /** + * Create a Duration representing an amount of minutes + * * @param amount the amount of Minutes the `Duration` will represent. * @returns a new `Duration` representing `amount` Minutes. */ @@ -34,6 +40,8 @@ export class Duration { } /** + * Create a Duration representing an amount of hours + * * @param amount the amount of Hours the `Duration` will represent. * @returns a new `Duration` representing `amount` Hours. */ @@ -42,6 +50,8 @@ export class Duration { } /** + * Create a Duration representing an amount of days + * * @param amount the amount of Days the `Duration` will represent. * @returns a new `Duration` representing `amount` Days. */ @@ -50,8 +60,9 @@ export class Duration { } /** - * Parse a period formatted according to the ISO 8601 standard (see https://www.iso.org/fr/standard/70907.html). + * Parse a period formatted according to the ISO 8601 standard * + * @see https://www.iso.org/fr/standard/70907.html * @param duration an ISO-formtted duration to be parsed. * @returns the parsed `Duration`. */ @@ -64,11 +75,11 @@ export class Duration { if (!days && !hours && !minutes && !seconds) { throw new Error(`Not a valid ISO duration: ${duration}`); } - return Duration.seconds( - _toInt(seconds) - + (_toInt(minutes) * TimeUnit.Minutes.inSeconds) - + (_toInt(hours) * TimeUnit.Hours.inSeconds) - + (_toInt(days) * TimeUnit.Days.inSeconds) + return Duration.millis( + _toInt(seconds) * TimeUnit.Seconds.inMillis + + (_toInt(minutes) * TimeUnit.Minutes.inMillis) + + (_toInt(hours) * TimeUnit.Hours.inMillis) + + (_toInt(days) * TimeUnit.Days.inMillis) ); function _toInt(str: string): number { @@ -90,6 +101,8 @@ export class Duration { } /** + * Return the total number of milliseconds in this Duration + * * @returns the value of this `Duration` expressed in Milliseconds. */ public toMilliseconds(opts: TimeConversionOptions = {}): number { @@ -97,6 +110,8 @@ export class Duration { } /** + * Return the total number of seconds in this Duration + * * @returns the value of this `Duration` expressed in Seconds. */ public toSeconds(opts: TimeConversionOptions = {}): number { @@ -104,6 +119,8 @@ export class Duration { } /** + * Return the total number of minutes in this Duration + * * @returns the value of this `Duration` expressed in Minutes. */ public toMinutes(opts: TimeConversionOptions = {}): number { @@ -111,6 +128,8 @@ export class Duration { } /** + * Return the total number of hours in this Duration + * * @returns the value of this `Duration` expressed in Hours. */ public toHours(opts: TimeConversionOptions = {}): number { @@ -118,6 +137,8 @@ export class Duration { } /** + * Return the total number of days in this Duration + * * @returns the value of this `Duration` expressed in Days. */ public toDays(opts: TimeConversionOptions = {}): number { @@ -125,9 +146,12 @@ export class Duration { } /** - * @returns an ISO 8601 representation of this period (see https://www.iso.org/fr/standard/70907.html). + * Return an ISO 8601 representation of this period + * + * @returns a string starting with 'PT' describing the period + * @see https://www.iso.org/fr/standard/70907.html */ - public toISOString(): string { + public toIsoString(): string { if (this.amount === 0) { return 'PT0S'; } switch (this.unit) { case TimeUnit.Seconds: @@ -143,6 +167,52 @@ export class Duration { } } + /** + * Return an ISO 8601 representation of this period + * + * @returns a string starting with 'PT' describing the period + * @see https://www.iso.org/fr/standard/70907.html + * @deprecated Use `toIsoString()` instead. + */ + public toISOString(): string { + return this.toIsoString(); + } + + /** + * Turn this duration into a human-readable string + */ + public toHumanString(): string { + if (this.amount === 0) { return fmtUnit(0, this.unit); } + if (Token.isUnresolved(this.amount)) { return ` ${this.unit.label}`; } + + let millis = convert(this.amount, this.unit, TimeUnit.Milliseconds, { integral: false }); + const parts = new Array(); + + for (const unit of [TimeUnit.Days, TimeUnit.Hours, TimeUnit.Hours, TimeUnit.Minutes, TimeUnit.Seconds]) { + const wholeCount = Math.floor(convert(millis, TimeUnit.Milliseconds, unit, { integral: false })); + if (wholeCount > 0) { + parts.push(fmtUnit(wholeCount, unit)); + millis -= wholeCount * unit.inMillis; + } + } + + // Remainder in millis + if (millis > 0) { + parts.push(fmtUnit(millis, TimeUnit.Milliseconds)); + } + + // 2 significant parts, that's totally enough for humans + return parts.slice(0, 2).join(' '); + + function fmtUnit(amount: number, unit: TimeUnit) { + if (amount === 1) { + // All of the labels end in 's' + return `${amount} ${unit.label.substring(0, unit.label.length - 1)}`; + } + return `${amount} ${unit.label}`; + } + } + /** * Returns a string representation of this `Duration` that is also a Token that cannot be successfully resolved. This * protects users against inadvertently stringifying a `Duration` object, when they should have called one of the @@ -183,13 +253,16 @@ export interface TimeConversionOptions { } class TimeUnit { - public static readonly Milliseconds = new TimeUnit('millis', 0.001); - public static readonly Seconds = new TimeUnit('seconds', 1); - public static readonly Minutes = new TimeUnit('minutes', 60); - public static readonly Hours = new TimeUnit('hours', 3_600); - public static readonly Days = new TimeUnit('days', 86_400); + public static readonly Milliseconds = new TimeUnit('millis', 1); + public static readonly Seconds = new TimeUnit('seconds', 1_000); + public static readonly Minutes = new TimeUnit('minutes', 60_000); + public static readonly Hours = new TimeUnit('hours', 3_600_000); + public static readonly Days = new TimeUnit('days', 86_400_000); - private constructor(public readonly label: string, public readonly inSeconds: number) { + private constructor(public readonly label: string, public readonly inMillis: number) { + // MAX_SAFE_INTEGER is 2^53, so by representing our duration in millis (the lowest + // common unit) the highest duration we can represent is + // 2^53 / 86*10^6 ~= 104 * 10^6 days (about 100 million days). } public toString() { @@ -198,8 +271,8 @@ class TimeUnit { } function convert(amount: number, fromUnit: TimeUnit, toUnit: TimeUnit, { integral = true }: TimeConversionOptions) { - if (fromUnit.inSeconds === toUnit.inSeconds) { return amount; } - const multiplier = fromUnit.inSeconds / toUnit.inSeconds; + if (fromUnit.inMillis === toUnit.inMillis) { return amount; } + const multiplier = fromUnit.inMillis / toUnit.inMillis; if (Token.isUnresolved(amount)) { throw new Error(`Unable to perform time unit conversion on un-resolved token ${amount}.`); diff --git a/packages/@aws-cdk/core/package.json b/packages/@aws-cdk/core/package.json index cff11f68a3298..3e32e60453cd7 100644 --- a/packages/@aws-cdk/core/package.json +++ b/packages/@aws-cdk/core/package.json @@ -57,17 +57,6 @@ "docs-public-apis:@aws-cdk/core.ConstructNode.root", "docs-public-apis:@aws-cdk/core.ContextProvider.getKey", "docs-public-apis:@aws-cdk/core.ContextProvider.getValue", - "docs-public-apis:@aws-cdk/core.Duration.days", - "docs-public-apis:@aws-cdk/core.Duration.hours", - "docs-public-apis:@aws-cdk/core.Duration.millis", - "docs-public-apis:@aws-cdk/core.Duration.minutes", - "docs-public-apis:@aws-cdk/core.Duration.seconds", - "docs-public-apis:@aws-cdk/core.Duration.toDays", - "docs-public-apis:@aws-cdk/core.Duration.toHours", - "docs-public-apis:@aws-cdk/core.Duration.toISOString", - "docs-public-apis:@aws-cdk/core.Duration.toMilliseconds", - "docs-public-apis:@aws-cdk/core.Duration.toMinutes", - "docs-public-apis:@aws-cdk/core.Duration.toSeconds", "docs-public-apis:@aws-cdk/core.Lazy.anyValue", "docs-public-apis:@aws-cdk/core.Lazy.listValue", "docs-public-apis:@aws-cdk/core.Lazy.numberValue", diff --git a/packages/@aws-cdk/core/test/test.duration.ts b/packages/@aws-cdk/core/test/test.duration.ts index 41a7a6cc110c7..81e0822b55a77 100644 --- a/packages/@aws-cdk/core/test/test.duration.ts +++ b/packages/@aws-cdk/core/test/test.duration.ts @@ -1,5 +1,5 @@ import * as nodeunit from 'nodeunit'; -import { Duration, Stack, Token } from '../lib'; +import { Duration, Lazy, Stack, Token } from '../lib'; export = nodeunit.testCase({ 'negative amount'(test: nodeunit.Test) { @@ -93,6 +93,22 @@ export = nodeunit.testCase({ test.done(); }, + 'toIsoString'(test: nodeunit.Test) { + test.equal(Duration.seconds(0).toIsoString(), 'PT0S'); + test.equal(Duration.minutes(0).toIsoString(), 'PT0S'); + test.equal(Duration.hours(0).toIsoString(), 'PT0S'); + test.equal(Duration.days(0).toIsoString(), 'PT0S'); + + test.equal(Duration.seconds(5).toIsoString(), 'PT5S'); + test.equal(Duration.minutes(5).toIsoString(), 'PT5M'); + test.equal(Duration.hours(5).toIsoString(), 'PT5H'); + test.equal(Duration.days(5).toIsoString(), 'PT5D'); + + test.equal(Duration.seconds(1 + 60 * (1 + 60 * (1 + 24))).toIsoString(), 'PT1D1H1M1S'); + + test.done(); + }, + 'parse'(test: nodeunit.Test) { test.equal(Duration.parse('PT0S').toSeconds(), 0); test.equal(Duration.parse('PT0M').toSeconds(), 0); @@ -107,7 +123,26 @@ export = nodeunit.testCase({ test.equal(Duration.parse('PT1D1H1M1S').toSeconds(), 1 + 60 * (1 + 60 * (1 + 24))); test.done(); - } + }, + + 'to human string'(test: nodeunit.Test) { + test.equal(Duration.minutes(0).toHumanString(), '0 minutes'); + test.equal(Duration.minutes(Lazy.numberValue({ produce: () => 5 })).toHumanString(), ' minutes'); + + test.equal(Duration.minutes(10).toHumanString(), '10 minutes'); + test.equal(Duration.minutes(1).toHumanString(), '1 minute'); + + test.equal(Duration.minutes(62).toHumanString(), '1 hour 2 minutes'); + + test.equal(Duration.seconds(3666).toHumanString(), '1 hour 1 minute'); + + test.equal(Duration.millis(3000).toHumanString(), '3 seconds'); + test.equal(Duration.millis(3666).toHumanString(), '3 seconds 666 millis'); + + test.equal(Duration.millis(3.6).toHumanString(), '3.6 millis'); + + test.done(); + }, }); function floatEqual(test: nodeunit.Test, actual: number, expected: number) { diff --git a/packages/@aws-cdk/custom-resources/README.md b/packages/@aws-cdk/custom-resources/README.md index 13cd4a4002fe3..e75d619a7875e 100644 --- a/packages/@aws-cdk/custom-resources/README.md +++ b/packages/@aws-cdk/custom-resources/README.md @@ -380,6 +380,19 @@ Since a successful resource provisioning might or might not produce outputs, thi In both the cases, you will get a synth time error if you attempt to use it in conjunction with `ignoreErrorCodesMatching`. +### Customizing the Lambda function implementing the custom resource +Use the `role`, `timeout` and `logRetention` properties to customize the Lambda function implementing the custom +resource: + +```ts +new AwsCustomResource(this, 'Customized', { + // other props here + role: myRole, // must be assumable by the `lambda.amazonaws.com` service principal + timeout: cdk.Duration.minutes(10) // defaults to 2 minutes + logRetention: logs.RetentionDays.ONE_WEEK // defaults to never delete logs +}) +``` + ### Examples #### Verify a domain with SES diff --git a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/aws-custom-resource.ts b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/aws-custom-resource.ts index 881954c056e97..e0ea2b0d06199 100644 --- a/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/aws-custom-resource.ts +++ b/packages/@aws-cdk/custom-resources/lib/aws-custom-resource/aws-custom-resource.ts @@ -1,6 +1,7 @@ import { CustomResource, CustomResourceProvider } from '@aws-cdk/aws-cloudformation'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; +import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; import * as fs from 'fs'; import * as path from 'path'; @@ -235,6 +236,14 @@ export interface AwsCustomResourceProps { * @default Duration.minutes(2) */ readonly timeout?: cdk.Duration + + /** + * The number of days log events of the Lambda function implementing + * this custom resource are kept in CloudWatch Logs. + * + * @default logs.RetentionDays.INFINITE + */ + readonly logRetention?: logs.RetentionDays; } /** @@ -292,6 +301,7 @@ export class AwsCustomResource extends cdk.Construct implements iam.IGrantable { lambdaPurpose: 'AWS', timeout: props.timeout || cdk.Duration.minutes(2), role: props.role, + logRetention: props.logRetention, }); this.grantPrincipal = provider.grantPrincipal; diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 38264cb2ad94a..9074a5a103459 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -73,7 +73,7 @@ "@types/aws-lambda": "^8.10.39", "@types/fs-extra": "^8.1.0", "@types/sinon": "^7.5.2", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "aws-sdk-mock": "^5.1.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", @@ -87,6 +87,7 @@ "@aws-cdk/aws-cloudformation": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", "@aws-cdk/aws-stepfunctions-tasks": "0.0.0", @@ -97,6 +98,7 @@ "@aws-cdk/aws-cloudformation": "0.0.0", "@aws-cdk/aws-iam": "0.0.0", "@aws-cdk/aws-lambda": "0.0.0", + "@aws-cdk/aws-logs": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-stepfunctions": "0.0.0", "@aws-cdk/aws-stepfunctions-tasks": "0.0.0", 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 27e3b89311703..4f5dcc5ec34d0 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,5 +1,6 @@ import '@aws-cdk/assert/jest'; import * as iam from '@aws-cdk/aws-iam'; +import * as logs from '@aws-cdk/aws-logs'; import * as cdk from '@aws-cdk/core'; import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from '../../lib'; @@ -488,3 +489,35 @@ test('getDataString', () => { } }); }); + +test('can specify log retention', () => { + // GIVEN + const stack = new cdk.Stack(); + + // WHEN + new AwsCustomResource(stack, 'AwsSdk', { + onCreate: { + service: 'service', + action: 'action', + physicalResourceId: PhysicalResourceId.of('id') + }, + logRetention: logs.RetentionDays.ONE_WEEK, + policy: AwsCustomResourcePolicy.fromSdkCalls({ resources: AwsCustomResourcePolicy.ANY_RESOURCE }) + }); + + // THEN + expect(stack).toHaveResource('Custom::LogRetention', { + LogGroupName: { + 'Fn::Join': [ + '', + [ + '/aws/lambda/', + { + Ref: 'AWS679f53fac002430cb0da5b7982bd22872D164C4C' + } + ] + ] + }, + RetentionInDays: 7 + }); +}); diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index f569653353061..0f917dc7cdef6 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -70,7 +70,7 @@ "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", "archiver": "^3.1.1", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "camelcase": "^5.3.1", "cdk-assets": "0.0.0", "colors": "^1.4.0", diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index aca5245dcb214..1a12fca46461a 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -44,7 +44,7 @@ "dependencies": { "@aws-cdk/cdk-assets-schema": "0.0.0", "archiver": "^3.1.1", - "aws-sdk": "^2.637.0", + "aws-sdk": "^2.638.0", "glob": "^7.1.6", "yargs": "^15.3.0" }, diff --git a/yarn.lock b/yarn.lock index 600dea4704722..5f36b89aacdbe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2359,11 +2359,6 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -app-root-path@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" - integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== - append-transform@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" @@ -2606,10 +2601,10 @@ aws-sdk-mock@^5.1.0: sinon "^9.0.1" traverse "^0.6.6" -aws-sdk@^2.637.0: - version "2.637.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.637.0.tgz#810e25e53acf2250d35fc74498f9d4492e154217" - integrity sha512-e7EYX5rNtQyEaleQylUtLSNKXOmvOwfifQ4bYkfF80mFsVI3DSydczLHXrqPzXoEJaS/GI/9HqVnlQcPs6Q3ew== +aws-sdk@^2.637.0, aws-sdk@^2.638.0: + version "2.638.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.638.0.tgz#43df5a956696177c577b841ea21b4007a81dbdaa" + integrity sha512-DOSwedH2YkPVs3c2AQezK6FHuGRIDffgULGvmpY9ZmZ/x45Sw+p7WHCYPgWfw/Z1fJWzMjaIpu531xG7pyJV4A== dependencies: buffer "4.9.1" events "1.1.1" @@ -4499,21 +4494,11 @@ dotenv-expand@^5.1.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== -dotenv-json@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dotenv-json/-/dotenv-json-1.0.0.tgz#fc7f672aafea04bed33818733b9f94662332815c" - integrity sha512-jAssr+6r4nKhKRudQ0HOzMskOFFi9+ubXWwmrSGJFgTvpjyPXCXsCsYbjif6mXp7uxA7xY3/LGaiTQukZzSbOQ== - dotenv@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow== -dotenv@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" - integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== - dotgitignore@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" @@ -4748,11 +4733,6 @@ escodegen@~1.9.0: optionalDependencies: source-map "~0.6.1" -eslint-config-standard@^14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4" - integrity sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA== - eslint-import-resolver-node@^0.3.2, eslint-import-resolver-node@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" @@ -4780,15 +4760,7 @@ eslint-module-utils@^2.4.1: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-es@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz#0f5f5da5f18aa21989feebe8a73eadefb3432976" - integrity sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ== - dependencies: - eslint-utils "^1.4.2" - regexpp "^3.0.0" - -eslint-plugin-import@^2.19.1, eslint-plugin-import@^2.20.1: +eslint-plugin-import@^2.20.1: version "2.20.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3" integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw== @@ -4806,28 +4778,6 @@ eslint-plugin-import@^2.19.1, eslint-plugin-import@^2.20.1: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-node@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz#fd1adbc7a300cf7eb6ac55cf4b0b6fc6e577f5a6" - integrity sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ== - dependencies: - eslint-plugin-es "^2.0.0" - eslint-utils "^1.4.2" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - -eslint-plugin-promise@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== - -eslint-plugin-standard@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" - integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== - eslint-scope@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" @@ -4836,7 +4786,7 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.4.2, eslint-utils@^1.4.3: +eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== @@ -5968,11 +5918,6 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1: - version "5.1.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" - integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== - immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" @@ -7302,24 +7247,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lambda-leak@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lambda-leak/-/lambda-leak-2.0.0.tgz#771985d3628487f6e885afae2b54510dcfb2cd7e" - integrity sha1-dxmF02KEh/boha+uK1RRDc+yzX4= - -lambda-tester@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/lambda-tester/-/lambda-tester-3.6.0.tgz#ceb7d4f4f0da768487a05cff37dcd088508b5247" - integrity sha512-F2ZTGWCLyIR95o/jWK46V/WnOCFAEUG/m/V7/CLhPJ7PCM+pror1rZ6ujP3TkItSGxUfpJi0kqwidw+M/nEqWw== - dependencies: - app-root-path "^2.2.1" - dotenv "^8.0.0" - dotenv-json "^1.0.0" - lambda-leak "^2.0.0" - semver "^6.1.1" - uuid "^3.3.2" - vandium-utils "^1.1.1" - lazystream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" @@ -8096,17 +8023,6 @@ nise@^4.0.1: just-extend "^4.0.2" path-to-regexp "^1.7.0" -nock@^11.7.0: - version "11.9.1" - resolved "https://registry.yarnpkg.com/nock/-/nock-11.9.1.tgz#2b026c5beb6d0dbcb41e7e4cefa671bc36db9c61" - integrity sha512-U5wPctaY4/ar2JJ5Jg4wJxlbBfayxgKbiAeGh+a1kk6Pwnc2ZEuKviLyDSG6t0uXl56q7AALIxoM6FJrBSsVXA== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.13" - mkdirp "^0.5.0" - propagate "^2.0.0" - nock@^12.0.2: version "12.0.2" resolved "https://registry.yarnpkg.com/nock/-/nock-12.0.2.tgz#47617b34738e026b29d2294b4579e35b27e6a4d3" @@ -10158,13 +10074,6 @@ resolve@1.x, resolve@^1.1.5, resolve@^1.10.0, resolve@^1.11.1, resolve@^1.12.0, dependencies: path-parse "^1.0.6" -resolve@^1.10.1: - version "1.15.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" - integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== - dependencies: - path-parse "^1.0.6" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -10327,7 +10236,7 @@ semver-intersect@^1.4.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@6.3.0, semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -11428,22 +11337,6 @@ trivial-deferred@^1.0.1: resolved "https://registry.yarnpkg.com/trivial-deferred/-/trivial-deferred-1.0.1.tgz#376d4d29d951d6368a6f7a0ae85c2f4d5e0658f3" integrity sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM= -ts-jest@^24.2.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.3.0.tgz#b97814e3eab359ea840a1ac112deae68aa440869" - integrity sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ== - dependencies: - bs-logger "0.x" - buffer-from "1.x" - fast-json-stable-stringify "2.x" - json5 "2.x" - lodash.memoize "4.x" - make-error "1.x" - mkdirp "0.x" - resolve "1.x" - semver "^5.5" - yargs-parser "10.x" - ts-jest@^25.2.0: version "25.2.1" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.2.1.tgz#49bf05da26a8b7fbfbc36b4ae2fcdc2fef35c85d" @@ -11840,11 +11733,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vandium-utils@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vandium-utils/-/vandium-utils-1.2.0.tgz#44735de4b7641a05de59ebe945f174e582db4f59" - integrity sha1-RHNd5LdkGgXeWevpRfF05YLbT1k= - vendors@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" @@ -12200,7 +12088,7 @@ yapool@^1.0.0: resolved "https://registry.yarnpkg.com/yapool/-/yapool-1.0.0.tgz#f693f29a315b50d9a9da2646a7a6645c96985b6a" integrity sha1-9pPymjFbUNmp2iZGp6ZkXJaYW2o= -yargs-parser@10.x, yargs-parser@^10.0.0: +yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==