diff --git a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts index 8df78cf2aaef1..1b25fa8e2f742 100644 --- a/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts +++ b/packages/@aws-cdk/aws-ec2/lib/vpc-endpoint.ts @@ -322,6 +322,7 @@ export class InterfaceVpcEndpointAwsService implements IInterfaceVpcEndpointServ public static readonly LAMBDA = new InterfaceVpcEndpointAwsService('lambda'); public static readonly TRANSCRIBE = new InterfaceVpcEndpointAwsService('transcribe'); public static readonly XRAY = new InterfaceVpcEndpointAwsService('xray'); + public static readonly SECURITYHUB = new InterfaceVpcEndpointAwsService('securityhub'); /** * The name of the service. e.g. com.amazonaws.us-east-1.ecs diff --git a/packages/@aws-cdk/aws-ec2/package.json b/packages/@aws-cdk/aws-ec2/package.json index a6cdea1064707..5ed0d723801f8 100644 --- a/packages/@aws-cdk/aws-ec2/package.json +++ b/packages/@aws-cdk/aws-ec2/package.json @@ -323,6 +323,7 @@ "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.LAMBDA", "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.TRANSCRIBE", "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.XRAY", + "docs-public-apis:@aws-cdk/aws-ec2.InterfaceVpcEndpointAwsService.SECURITYHUB", "docs-public-apis:@aws-cdk/aws-ec2.Port.toString", "docs-public-apis:@aws-cdk/aws-ec2.PrivateSubnet.fromPrivateSubnetAttributes", "docs-public-apis:@aws-cdk/aws-ec2.PublicSubnet.fromPublicSubnetAttributes", diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/imported.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/imported.ts index 72c4ce3969885..889565ffb0d93 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/imported.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/imported.ts @@ -30,7 +30,7 @@ export abstract class ImportedTargetGroupBase extends Construct implements ITarg super(scope, id); this.targetGroupArn = props.targetGroupArn; - this.targetGroupName = cdk.Stack.of(scope).splitArn(props.targetGroupArn, cdk.ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME).resourceName!.split('/')[0]; + this.targetGroupName = cdk.Stack.of(scope).splitArn(props.targetGroupArn, cdk.ArnFormat.SLASH_RESOURCE_NAME).resourceName!.split('/')[0]; this.loadBalancerArns = props.loadBalancerArns || cdk.Aws.NO_VALUE; } } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts index 57a3aabe6a11b..a8305cd2a34f2 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/target-group.test.ts @@ -541,4 +541,51 @@ describe('tests', () => { // THEN expect(importedTg.targetGroupName).toEqual('myAlbTargetGroup'); }); + + test('imported targetGroup with imported ARN has targetGroupName', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack'); + + // WHEN + const importedTgArn = cdk.Fn.importValue('ImportTargetGroupArn'); + const importedTg = elbv2.ApplicationTargetGroup.fromTargetGroupAttributes(stack, 'importedTg', { + targetGroupArn: importedTgArn, + }); + new cdk.CfnOutput(stack, 'TargetGroupOutput', { + value: importedTg.targetGroupName, + }); + + // THEN + Template.fromStack(stack).hasOutput('TargetGroupOutput', { + Value: { + 'Fn::Select': [ + // myAlbTargetGroup + 1, + { + 'Fn::Split': [ + // [targetgroup, myAlbTargetGroup, 73e2d6bc24d8a067] + '/', + { + 'Fn::Select': [ + // targetgroup/myAlbTargetGroup/73e2d6bc24d8a067 + 5, + { + 'Fn::Split': [ + // [arn, aws, elasticloadbalancing, us-west-2, 123456789012, targetgroup/myAlbTargetGroup/73e2d6bc24d8a067] + ':', + { + // arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/myAlbTargetGroup/73e2d6bc24d8a067 + 'Fn::ImportValue': 'ImportTargetGroupArn', + }, + ], + }, + ], + }, + ], + }, + ], + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/target-group.test.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/target-group.test.ts index 4f634d82cfc00..6d94b4ee4d45e 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/target-group.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/target-group.test.ts @@ -635,4 +635,51 @@ describe('tests', () => { // THEN expect(importedTg.targetGroupName).toEqual('myNlbTargetGroup'); }); + + test('imported targetGroup with imported ARN has targetGroupName', () => { + // GIVEN + const app = new cdk.App(); + const stack = new cdk.Stack(app, 'Stack'); + + // WHEN + const importedTgArn = cdk.Fn.importValue('ImportTargetGroupArn'); + const importedTg = elbv2.ApplicationTargetGroup.fromTargetGroupAttributes(stack, 'importedTg', { + targetGroupArn: importedTgArn, + }); + new cdk.CfnOutput(stack, 'TargetGroupOutput', { + value: importedTg.targetGroupName, + }); + + // THEN + Template.fromStack(stack).hasOutput('TargetGroupOutput', { + Value: { + 'Fn::Select': [ + // myNlbTargetGroup + 1, + { + 'Fn::Split': [ + // [targetgroup, myNlbTargetGroup, 73e2d6bc24d8a067] + '/', + { + 'Fn::Select': [ + // targetgroup/myNlbTargetGroup/73e2d6bc24d8a067 + 5, + { + 'Fn::Split': [ + // [arn, aws, elasticloadbalancing, us-west-2, 123456789012, targetgroup/myNlbTargetGroup/73e2d6bc24d8a067] + ':', + { + // arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/myNlbTargetGroup/73e2d6bc24d8a067 + 'Fn::ImportValue': 'ImportTargetGroupArn', + }, + ], + }, + ], + }, + ], + }, + ], + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts index 88004a8f44c5f..975e006283b07 100644 --- a/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts +++ b/packages/@aws-cdk/aws-events-targets/test/logs/integ.log-group.ts @@ -2,8 +2,8 @@ import * as events from '@aws-cdk/aws-events'; import * as logs from '@aws-cdk/aws-logs'; import * as sqs from '@aws-cdk/aws-sqs'; import * as cdk from '@aws-cdk/core'; +import { IntegTest, ExpectedResult } from '@aws-cdk/integ-tests'; import * as targets from '../../lib'; -import { IntegTest, ExpectedResult, AssertionsProvider } from '@aws-cdk/integ-tests'; import { LogGroupTargetInput } from '../../lib'; const app = new cdk.App(); @@ -71,8 +71,7 @@ const putEvent = integ.assertions.awsApiCall('EventBridge', 'putEvents', { }, ], }); -const assertionProvider = putEvent.node.tryFindChild('SdkProvider') as AssertionsProvider; -assertionProvider.addPolicyStatementFromSdkCall('events', 'PutEvents'); +putEvent.provider.addPolicyStatementFromSdkCall('events', 'PutEvents'); const logEvents = integ.assertions.awsApiCall('CloudWatchLogs', 'filterLogEvents', { logGroupName: logGroup2.logGroupName, @@ -80,7 +79,7 @@ const logEvents = integ.assertions.awsApiCall('CloudWatchLogs', 'filterLogEvents limit: 1, }); -logEvents.node.addDependency(putEvent); +putEvent.next(logEvents); logEvents.assertAtPath('events.0.message', ExpectedResult.stringLikeRegexp(expectedValue)); diff --git a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts index d3bd0f112d726..211bbfd154b31 100644 --- a/packages/@aws-cdk/aws-rds/lib/instance-engine.ts +++ b/packages/@aws-cdk/aws-rds/lib/instance-engine.ts @@ -934,6 +934,8 @@ export class PostgresEngineVersion { public static readonly VER_11_14 = PostgresEngineVersion.of('11.14', '11', { s3Import: true, s3Export: true }); /** Version "11.15". */ public static readonly VER_11_15 = PostgresEngineVersion.of('11.15', '11', { s3Import: true, s3Export: true }); + /** Version "11.16". */ + public static readonly VER_11_16 = PostgresEngineVersion.of('11.16', '11', { s3Import: true, s3Export: true }); /** Version "12" (only a major version, without a specific minor version). */ public static readonly VER_12 = PostgresEngineVersion.of('12', '12', { s3Import: true }); diff --git a/packages/@aws-cdk/integ-tests/README.md b/packages/@aws-cdk/integ-tests/README.md index 205e0699c88c9..7145e3c2d0ff4 100644 --- a/packages/@aws-cdk/integ-tests/README.md +++ b/packages/@aws-cdk/integ-tests/README.md @@ -182,7 +182,7 @@ There are two main scenarios in which assertions are created. - Part of an integration test using `integ-runner` In this case you would create an integration test using the `IntegTest` construct and then make assertions using the `assert` property. -You should **not** utilize the assertion constructs directly, but should instead use the `methods` on `IntegTest.assert`. +You should **not** utilize the assertion constructs directly, but should instead use the `methods` on `IntegTest.assertions`. ```ts declare const app: App; @@ -410,3 +410,21 @@ describe.expect(ExpectedResult.objectLike({ })); ``` +#### Chain ApiCalls + +Sometimes it may be necessary to chain API Calls. Since each API call is its own resource, all you +need to do is add a dependency between the calls. There is an helper method `next` that can be used. + +```ts +declare const integ: IntegTest; + +integ.assertions.awsApiCall('S3', 'putObject', { + Bucket: 'my-bucket', + Key: 'my-key', + Body: 'helloWorld', +}).next(integ.assertions.awsApiCall('S3', 'getObject', { + Bucket: 'my-bucket', + Key: 'my-key', +})); +``` + diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts b/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts new file mode 100644 index 0000000000000..08fd3885e61d8 --- /dev/null +++ b/packages/@aws-cdk/integ-tests/lib/assertions/api-call-base.ts @@ -0,0 +1,139 @@ +import { CustomResource, Reference } from '@aws-cdk/core'; +import { Construct, IConstruct } from 'constructs'; +import { ExpectedResult } from './common'; +import { AssertionsProvider } from './providers'; + +/** + * Represents an ApiCall + */ +export interface IApiCall extends IConstruct { + /** + * access the AssertionsProvider. This can be used to add additional IAM policies + * the the provider role policy + * + * @example + * declare const apiCall: AwsApiCall; + * apiCall.provider.addToRolePolicy({ + * Effect: 'Allow', + * Action: ['s3:GetObject'], + * Resource: ['*'], + * }); + */ + readonly provider: AssertionsProvider; + + /** + * Returns the value of an attribute of the custom resource of an arbitrary + * type. Attributes are returned from the custom resource provider through the + * `Data` map where the key is the attribute name. + * + * @param attributeName the name of the attribute + * @returns a token for `Fn::GetAtt`. Use `Token.asXxx` to encode the returned `Reference` as a specific type or + * use the convenience `getAttString` for string attributes. + */ + getAtt(attributeName: string): Reference; + + /** + * Returns the value of an attribute of the custom resource of type string. + * Attributes are returned from the custom resource provider through the + * `Data` map where the key is the attribute name. + * + * @param attributeName the name of the attribute + * @returns a token for `Fn::GetAtt` encoded as a string. + */ + getAttString(attributeName: string): string; + + /** + * Assert that the ExpectedResult is equal + * to the result of the AwsApiCall + * + * @example + * declare const integ: IntegTest; + * const invoke = integ.assertions.invokeFunction({ + * functionName: 'my-func', + * }); + * invoke.expect(ExpectedResult.objectLike({ Payload: 'OK' })); + */ + expect(expected: ExpectedResult): void; + + /** + * Assert that the ExpectedResult is equal + * to the result of the AwsApiCall at the given path. + * + * For example the SQS.receiveMessage api response would look + * like: + * + * If you wanted to assert the value of `Body` you could do + * + * @example + * const actual = { + * Messages: [{ + * MessageId: '', + * ReceiptHandle: '', + * MD5OfBody: '', + * Body: 'hello', + * Attributes: {}, + * MD5OfMessageAttributes: {}, + * MessageAttributes: {} + * }] + * }; + * + * + * declare const integ: IntegTest; + * const message = integ.assertions.awsApiCall('SQS', 'receiveMessage'); + * + * message.assertAtPath('Messages.0.Body', ExpectedResult.stringLikeRegexp('hello')); + */ + assertAtPath(path: string, expected: ExpectedResult): void; + + /** + * Allows you to chain IApiCalls. This adds an explicit dependency + * betweent the two resources. + * + * Returns the IApiCall provided as `next` + * + * @example + * declare const first: IApiCall; + * declare const second: IApiCall; + * + * first.next(second); + */ + next(next: IApiCall): IApiCall; +} + +/** + * Base class for an ApiCall + */ +export abstract class ApiCallBase extends Construct implements IApiCall { + protected abstract readonly apiCallResource: CustomResource; + protected expectedResult?: string; + protected flattenResponse: string = 'false'; + protected stateMachineArn?: string; + + public abstract readonly provider: AssertionsProvider; + + constructor(scope: Construct, id: string) { + super(scope, id); + + } + + public getAtt(attributeName: string): Reference { + this.flattenResponse = 'true'; + return this.apiCallResource.getAtt(`apiCallResponse.${attributeName}`); + } + + public getAttString(attributeName: string): string { + this.flattenResponse = 'true'; + return this.apiCallResource.getAttString(`apiCallResponse.${attributeName}`); + } + + public expect(expected: ExpectedResult): void { + this.expectedResult = expected.result; + } + + public abstract assertAtPath(path: string, expected: ExpectedResult): void; + + public next(next: IApiCall): IApiCall { + next.node.addDependency(this); + return next; + } +} diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/common.ts b/packages/@aws-cdk/integ-tests/lib/assertions/common.ts index 6daa9e510133c..13c1e50cddc08 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/common.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/common.ts @@ -1,5 +1,5 @@ import { CustomResource } from '@aws-cdk/core'; -import { IAwsApiCall } from './sdk'; +import { IApiCall } from './api-call-base'; /** * Represents the "actual" results to compare @@ -17,7 +17,7 @@ export abstract class ActualResult { /** * Get the actual results from a AwsApiCall */ - public static fromAwsApiCall(query: IAwsApiCall, attribute: string): ActualResult { + public static fromAwsApiCall(query: IApiCall, attribute: string): ActualResult { return { result: query.getAttString(attribute), }; diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/index.ts b/packages/@aws-cdk/integ-tests/lib/assertions/index.ts index 6622ddabcb560..b81ba41add625 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/index.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/index.ts @@ -4,3 +4,4 @@ export * from './assertions'; export * from './providers'; export * from './common'; export * from './match'; +export * from './api-call-base'; diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/private/deploy-assert.ts b/packages/@aws-cdk/integ-tests/lib/assertions/private/deploy-assert.ts index 068350c459aab..321082d7f8ce4 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/private/deploy-assert.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/private/deploy-assert.ts @@ -1,9 +1,10 @@ import { Stack } from '@aws-cdk/core'; import { Construct, IConstruct, Node } from 'constructs'; +import { IApiCall } from '../api-call-base'; import { EqualsAssertion } from '../assertions'; import { ExpectedResult, ActualResult } from '../common'; import { md5hash } from '../private/hash'; -import { AwsApiCall, LambdaInvokeFunction, IAwsApiCall, LambdaInvokeFunctionProps } from '../sdk'; +import { AwsApiCall, LambdaInvokeFunction, LambdaInvokeFunctionProps } from '../sdk'; import { IDeployAssert } from '../types'; @@ -49,7 +50,7 @@ export class DeployAssert extends Construct implements IDeployAssert { Object.defineProperty(this, DEPLOY_ASSERT_SYMBOL, { value: true }); } - public awsApiCall(service: string, api: string, parameters?: any): IAwsApiCall { + public awsApiCall(service: string, api: string, parameters?: any): IApiCall { return new AwsApiCall(this.scope, `AwsApiCall${service}${api}`, { api, service, @@ -57,7 +58,7 @@ export class DeployAssert extends Construct implements IDeployAssert { }); } - public invokeFunction(props: LambdaInvokeFunctionProps): IAwsApiCall { + public invokeFunction(props: LambdaInvokeFunctionProps): IApiCall { const hash = md5hash(this.scope.resolve(props)); return new LambdaInvokeFunction(this.scope, `LambdaInvoke${hash}`, props); } diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/sdk.ts b/packages/@aws-cdk/integ-tests/lib/assertions/sdk.ts index b79ecc4bce356..148ba0cc6a415 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/sdk.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/sdk.ts @@ -1,93 +1,10 @@ import { ArnFormat, CfnResource, CustomResource, Lazy, Reference, Stack } from '@aws-cdk/core'; -import { Construct, IConstruct } from 'constructs'; +import { Construct } from 'constructs'; +import { ApiCallBase } from './api-call-base'; import { EqualsAssertion } from './assertions'; import { ActualResult, ExpectedResult } from './common'; import { AssertionsProvider, SDK_RESOURCE_TYPE_PREFIX } from './providers'; -/** - * Interface for creating a custom resource that will perform - * an API call using the AWS SDK - */ -export interface IAwsApiCall extends IConstruct { - /** - * access the AssertionsProvider. This can be used to add additional IAM policies - * the the provider role policy - * - * @example - * declare const apiCall: AwsApiCall; - * apiCall.provider.addToRolePolicy({ - * Effect: 'Allow', - * Action: ['s3:GetObject'], - * Resource: ['*'], - * }); - */ - readonly provider: AssertionsProvider; - - /** - * Returns the value of an attribute of the custom resource of an arbitrary - * type. Attributes are returned from the custom resource provider through the - * `Data` map where the key is the attribute name. - * - * @param attributeName the name of the attribute - * @returns a token for `Fn::GetAtt`. Use `Token.asXxx` to encode the returned `Reference` as a specific type or - * use the convenience `getAttString` for string attributes. - */ - getAtt(attributeName: string): Reference; - - /** - * Returns the value of an attribute of the custom resource of type string. - * Attributes are returned from the custom resource provider through the - * `Data` map where the key is the attribute name. - * - * @param attributeName the name of the attribute - * @returns a token for `Fn::GetAtt` encoded as a string. - */ - getAttString(attributeName: string): string; - - /** - * Assert that the ExpectedResult is equal - * to the result of the AwsApiCall - * - * @example - * declare const integ: IntegTest; - * const invoke = integ.assertions.invokeFunction({ - * functionName: 'my-func', - * }); - * invoke.expect(ExpectedResult.objectLike({ Payload: 'OK' })); - */ - expect(expected: ExpectedResult): void; - - /** - * Assert that the ExpectedResult is equal - * to the result of the AwsApiCall at the given path. - * - * For example the SQS.receiveMessage api response would look - * like: - * - * If you wanted to assert the value of `Body` you could do - * - * @example - * const actual = { - * Messages: [{ - * MessageId: '', - * ReceiptHandle: '', - * MD5OfBody: '', - * Body: 'hello', - * Attributes: {}, - * MD5OfMessageAttributes: {}, - * MessageAttributes: {} - * }] - * }; - * - * - * declare const integ: IntegTest; - * const message = integ.assertions.awsApiCall('SQS', 'receiveMessage'); - * - * message.assertAtPath('Messages.0.Body', ExpectedResult.stringLikeRegexp('hello')); - */ - assertAtPath(path: string, expected: ExpectedResult): void; -} - /** * Options to perform an AWS JavaScript V2 API call */ @@ -119,9 +36,8 @@ export interface AwsApiCallProps extends AwsApiCallOptions { } * Construct that creates a custom resource that will perform * a query using the AWS SDK */ -export class AwsApiCall extends Construct implements IAwsApiCall { - private readonly sdkCallResource: CustomResource; - private flattenResponse: string = 'false'; +export class AwsApiCall extends ApiCallBase { + protected readonly apiCallResource: CustomResource; private readonly name: string; public readonly provider: AssertionsProvider; @@ -133,7 +49,7 @@ export class AwsApiCall extends Construct implements IAwsApiCall { this.provider.addPolicyStatementFromSdkCall(props.service, props.api); this.name = `${props.service}${props.api}`; - this.sdkCallResource = new CustomResource(this, 'Default', { + this.apiCallResource = new CustomResource(this, 'Default', { serviceToken: this.provider.serviceToken, properties: { service: props.service, @@ -146,23 +62,23 @@ export class AwsApiCall extends Construct implements IAwsApiCall { }); // Needed so that all the policies set up by the provider should be available before the custom resource is provisioned. - this.sdkCallResource.node.addDependency(this.provider); + this.apiCallResource.node.addDependency(this.provider); } public getAtt(attributeName: string): Reference { this.flattenResponse = 'true'; - return this.sdkCallResource.getAtt(`apiCallResponse.${attributeName}`); + return this.apiCallResource.getAtt(`apiCallResponse.${attributeName}`); } public getAttString(attributeName: string): string { this.flattenResponse = 'true'; - return this.sdkCallResource.getAttString(`apiCallResponse.${attributeName}`); + return this.apiCallResource.getAttString(`apiCallResponse.${attributeName}`); } public expect(expected: ExpectedResult): void { new EqualsAssertion(this, `AssertEquals${this.name}`, { expected, - actual: ActualResult.fromCustomResource(this.sdkCallResource, 'apiCallResponse'), + actual: ActualResult.fromCustomResource(this.apiCallResource, 'apiCallResponse'), }); } diff --git a/packages/@aws-cdk/integ-tests/lib/assertions/types.ts b/packages/@aws-cdk/integ-tests/lib/assertions/types.ts index 7c5dd185aa058..468eaf54b28ec 100644 --- a/packages/@aws-cdk/integ-tests/lib/assertions/types.ts +++ b/packages/@aws-cdk/integ-tests/lib/assertions/types.ts @@ -1,5 +1,6 @@ +import { IApiCall } from './api-call-base'; import { ExpectedResult, ActualResult } from './common'; -import { IAwsApiCall, LambdaInvokeFunctionProps } from './sdk'; +import { LambdaInvokeFunctionProps } from './sdk'; /** * Interface that allows for registering a list of assertions @@ -26,7 +27,7 @@ export interface IDeployAssert { * Messages: [{ Body: 'hello' }], * })); */ - awsApiCall(service: string, api: string, parameters?: any): IAwsApiCall; + awsApiCall(service: string, api: string, parameters?: any): IApiCall; /** * Invoke a lambda function and return the response which can be asserted @@ -41,7 +42,7 @@ export interface IDeployAssert { * Payload: '200', * })); */ - invokeFunction(props: LambdaInvokeFunctionProps): IAwsApiCall; + invokeFunction(props: LambdaInvokeFunctionProps): IApiCall; /** * Assert that the ExpectedResult is equal diff --git a/packages/@aws-cdk/integ-tests/package.json b/packages/@aws-cdk/integ-tests/package.json index d72add060b19a..477d73321010a 100644 --- a/packages/@aws-cdk/integ-tests/package.json +++ b/packages/@aws-cdk/integ-tests/package.json @@ -61,18 +61,18 @@ }, "license": "Apache-2.0", "devDependencies": { + "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/cx-api": "0.0.0", - "@aws-cdk/assertions": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/fs-extra": "^8.1.2", "@types/jest": "^27.5.2", "@types/node": "^14.18.29", + "aws-sdk": "^2.1093.0", + "aws-sdk-mock": "5.6.0", "jest": "^27.5.1", "nock": "^13.2.9", - "aws-sdk-mock": "5.6.0", - "sinon": "^9.2.4", - "aws-sdk": "^2.1093.0" + "sinon": "^9.2.4" }, "dependencies": { "@aws-cdk/cloud-assembly-schema": "0.0.0", diff --git a/packages/@aws-cdk/integ-tests/rosetta/default.ts-fixture b/packages/@aws-cdk/integ-tests/rosetta/default.ts-fixture index 7cf368abcf6db..168caf8aaf2af 100644 --- a/packages/@aws-cdk/integ-tests/rosetta/default.ts-fixture +++ b/packages/@aws-cdk/integ-tests/rosetta/default.ts-fixture @@ -4,6 +4,7 @@ import { IntegTest, IntegTestCaseStack, AwsApiCall, + IApiCall, EqualsAssertion, ActualResult, ExpectedResult, diff --git a/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts b/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts index 7be64290b1b01..3a03487425c5c 100644 --- a/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts +++ b/packages/@aws-cdk/integ-tests/test/assertions/sdk.test.ts @@ -22,6 +22,35 @@ describe('AwsApiCall', () => { }); }); + test('then', () => { + // GIVEN + const app = new App(); + const deplossert = new DeployAssert(app); + + // WHEN + const first = deplossert.awsApiCall('MyService', 'MyApi'); + first.next(deplossert.awsApiCall('MyOtherService', 'MyOtherApi')); + + // THEN + const template = Template.fromStack(deplossert.scope); + template.resourceCountIs('AWS::Lambda::Function', 1); + template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', { + service: 'MyService', + api: 'MyApi', + parameters: Match.absent(), + }); + template.hasResource('Custom::DeployAssert@SdkCallMyOtherServiceMyOtherApi', { + Properties: { + service: 'MyOtherService', + api: 'MyOtherApi', + parameters: Match.absent(), + }, + DependsOn: [ + 'AwsApiCallMyServiceMyApi', + ], + }); + }); + test('parameters', () => { // GIVEN const app = new App();