diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts index b254086ef..d937e6b3b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/lib/index.ts @@ -142,6 +142,7 @@ export class FargateToDynamoDB extends Construct { super(scope, id); defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckDynamoDBProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts index 5324cd6fb..1e535817d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-dynamodb/test/fargate-dynamodb.test.ts @@ -669,4 +669,48 @@ test('test error invalid table permission', () => { }; expect(app).toThrowError('Invalid tablePermission submitted - REED'); +}); + +test('test that DDB input args are getting checked', () => { + const stack = new cdk.Stack(); + const publicApi = false; + const serviceName = 'custom-name'; + const tableName = 'custom-table-name'; + + const existingVpc = defaults.getTestVpc(stack, publicApi); + + const createFargateServiceResponse = defaults.CreateFargateService(stack, 'test', { + constructVpc: existingVpc, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + clientFargateServiceProps: { + serviceName + } + }); + + const existingTable = new dynamodb.Table(stack, 'MyTablet', { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + } + }); + + const app = () => { + new FargateToDynamoDB(stack, 'test-construct', { + publicApi, + existingFargateServiceObject: createFargateServiceResponse.service, + existingContainerDefinitionObject: createFargateServiceResponse.containerDefinition, + existingVpc, + existingTableInterface: existingTable, + dynamoTableProps: { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + }, + }, + }); + }; + + expect(app).toThrowError('Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts index 5db6f1ce9..fb89e4034 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/lib/index.ts @@ -155,6 +155,7 @@ export class FargateToSns extends Construct { super(scope, id); defaults.CheckProps(props); defaults.CheckFargateProps(props); + defaults.CheckSnsProps(props); this.vpc = defaults.buildVpc(scope, { existingVpc: props.existingVpc, diff --git a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts index 3684666ae..b68b8da3f 100644 --- a/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-fargate-sns/test/fargate-sns.test.ts @@ -496,4 +496,34 @@ test('Topic is encrypted with customer managed KMS Key when enable encryption fl ] }, }); -}); \ No newline at end of file +}); + +test('Confirm CheckSnsProps is being called', () => { + // An environment with region is required to enable logging on an ALB + const stack = new cdk.Stack(undefined, undefined, { + env: { account: "123456789012", region: 'us-east-1' }, + }); + const publicApi = false; + const topicName = 'custom-topic-name'; + + const existingVpc = defaults.getTestVpc(stack, publicApi); + + const existingTopic = new sns.Topic(stack, 'MyTopic', { + topicName + }); + + const app = () => { + new FargateToSns(stack, 'test-construct', { + publicApi, + existingVpc, + ecrRepositoryArn: defaults.fakeEcrRepoArn, + existingTopicObject: existingTopic, + topicProps: { + topicName: 'topic-name' + }, + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts index 7426ed2a2..1a9715d69 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/lib/index.ts @@ -95,6 +95,7 @@ export class IotToLambdaToDynamoDB extends Construct { constructor(scope: Construct, id: string, props: IotToLambdaToDynamoDBProps) { super(scope, id); defaults.CheckProps(props); + defaults.CheckSnsProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts index 5a2aca4f6..42f7e8ff3 100644 --- a/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-iot-lambda-dynamodb/test/iot-lambda-dynamodb.test.ts @@ -616,3 +616,50 @@ test("Test bad call with existingVpc and deployVpc", () => { // Assertion expect(app).toThrowError(); }); + +// NOTE: existingTableObj was omitted from the interface for this construct, +// so this test cannot be run. Leaving it here so it can be used if/when existingTableObj +// is added to the interface +// +// test("Confirm CheckDynamoDBProps is getting called", () => { +// const stack = new cdk.Stack(); +// const tableName = 'table-name'; + +// const existingTable = new dynamodb.Table(stack, 'MyTablet', { +// tableName, +// partitionKey: { +// name: 'id', +// type: dynamodb.AttributeType.STRING +// } +// }); + +// const props: IotToLambdaToDynamoDBProps = { +// lambdaFunctionProps: { +// code: lambda.Code.fromAsset(`${__dirname}/lambda`), +// runtime: lambda.Runtime.NODEJS_16_X, +// handler: 'index.handler' +// }, +// iotTopicRuleProps: { +// topicRulePayload: { +// ruleDisabled: false, +// description: "Processing of DTC messages from the AWS Connected Vehicle Solution.", +// sql: "SELECT * FROM 'connectedcar/dtc/#'", +// actions: [] +// } +// }, +// existingTableObj: existingTable, +// dynamoTableProps: { +// tableName, +// partitionKey: { +// name: 'id', +// type: dynamodb.AttributeType.STRING +// }, +// }, +// }; + +// const app = () => { +// new IotToLambdaToDynamoDB(stack, 'test-iot-lambda-dynamodb-stack', props); +// }; + +// expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); +// }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts index 73cfa2d0e..2376bc92b 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/lib/index.ts @@ -91,6 +91,7 @@ export class LambdaToDynamoDB extends Construct { constructor(scope: Construct, id: string, props: LambdaToDynamoDBProps) { super(scope, id); defaults.CheckProps(props); + defaults.CheckDynamoDBProps(props); // Other permissions for constructs are accepted as arrays, turning tablePermissions into // an array to use the same validation function. diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts index 1b586b259..ea878a52a 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-dynamodb/test/lambda-dynamodb.test.ts @@ -802,4 +802,40 @@ test('Test bad table permission', () => { // Assertion expect(app).toThrowError(/Invalid table permission submitted - Reed/); +}); + +test('Test that CheckDynamoDBProps is getting called', () => { + const stack = new cdk.Stack(); + const tableName = 'custom-table-name'; + + const existingTable = new dynamodb.Table(stack, 'MyTablet', { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + } + }); + + const props: LambdaToDynamoDBProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTableObj: existingTable, + dynamoTableProps: { + tableName, + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING + }, + }, + }; + + const app = () => { + new LambdaToDynamoDB(stack, 'test-lambda-dynamodb-stack', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide existingTableObj or dynamoTableProps, but not both.\n/); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts index eb3072a10..765e36c99 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/lib/index.ts @@ -114,6 +114,7 @@ export class LambdaToSns extends Construct { constructor(scope: Construct, id: string, props: LambdaToSnsProps) { super(scope, id); defaults.CheckProps(props); + defaults.CheckSnsProps(props); if (props.deployVpc || props.existingVpc) { this.vpc = defaults.buildVpc(scope, { diff --git a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts index 9cb585c4c..145c7fbf2 100644 --- a/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-lambda-sns/test/lambda-sns.test.ts @@ -578,4 +578,31 @@ test('Error is thrown when conflicting VPC information is provided', () => { }; expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.'); +}); + +test('Test that CheckSnsProps is getting called', () => { + const stack = new Stack(); + + const topic = new sns.Topic(stack, 'MyTopic', { + topicName: "custom-topic" + }); + + const props: LambdaToSnsProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + }, + }; + + const app = () => { + new LambdaToSns(stack, 'test-lambda-dynamodb-stack', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts index 86ff8ea10..702c88eff 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/lib/index.ts @@ -86,6 +86,7 @@ export class SnsToLambda extends Construct { constructor(scope: Construct, id: string, props: SnsToLambdaProps) { super(scope, id); defaults.CheckProps(props); + defaults.CheckSnsProps(props); // Setup the Lambda function this.lambdaFunction = defaults.buildLambdaFunction(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts index 1e4f0b71c..d948929a0 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-lambda/test/sns-lambda.test.ts @@ -236,3 +236,30 @@ test('Topic is encrypted with customer managed KMS Key when enable encryption fl }, }); }); + +test('Confirm CheckSnsProps is getting called', () => { + const stack = new cdk.Stack(); + + const topic = new sns.Topic(stack, 'MyTopic', { + topicName: "custom-topic" + }); + + const props: SnsToLambdaProps = { + lambdaFunctionProps: { + code: lambda.Code.fromAsset(`${__dirname}/lambda`), + runtime: lambda.Runtime.NODEJS_16_X, + handler: 'index.handler' + }, + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + } + }; + + const app = () => { + new SnsToLambda(stack, 'test-sns-lambda', props); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); +}); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts index 142c719e4..d4955ef40 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/lib/index.ts @@ -116,6 +116,7 @@ export class SnsToSqs extends Construct { constructor(scope: Construct, id: string, props: SnsToSqsProps) { super(scope, id); defaults.CheckProps(props); + defaults.CheckSnsProps(props); // Setup the dead letter queue, if applicable this.deadLetterQueue = defaults.buildDeadLetterQueue(this, { diff --git a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts index 86278f8bd..6f5f3a79d 100644 --- a/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts +++ b/source/patterns/@aws-solutions-constructs/aws-sns-sqs/test/sns-sqs.test.ts @@ -132,9 +132,6 @@ test('Test getter methods', () => { expect(app.deadLetterQueue !== null); }); -// -------------------------------------------------------------- -// Test deployment with existing queue, and topic -// -------------------------------------------------------------- test('Test deployment w/ existing queue, and topic', () => { // Stack const stack = new Stack(); @@ -162,9 +159,6 @@ test('Test deployment w/ existing queue, and topic', () => { }); }); -// -------------------------------------------------------------- -// Test deployment with imported encryption key -// -------------------------------------------------------------- test('Test deployment with imported encryption key', () => { // Stack const stack = new Stack(); @@ -499,4 +493,29 @@ test('Construct does not override unencrypted topic when passed in existingTopic expect(testConstruct.snsTopic).toBeDefined(); expect(testConstruct.encryptionKey).not.toBeDefined(); +}); + +test('Confirm that CheckSnsProps is called', () => { + // Stack + const stack = new Stack(); + // Helper declaration + const topic = new sns.Topic(stack, "existing-topic-obj", { + topicName: 'existing-topic-obj' + }); + const queue = new sqs.Queue(stack, 'existing-queue-obj', { + queueName: 'existing-queue-obj' + }); + + const app = () => { + new SnsToSqs(stack, 'sns-to-sqs-stack', { + existingTopicObj: topic, + topicProps: { + topicName: 'topic-name' + }, + existingQueueObj: queue + }); + }; + + // Assertion + expect(app).toThrowError(/Error - Either provide topicProps or existingTopicObj, but not both.\n/); }); \ No newline at end of file diff --git a/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts b/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts index 1043d8f4a..c832c79b8 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/fargate-helper.ts @@ -224,16 +224,7 @@ export function CheckFargateProps(props: any) { let errorMessages = ""; let errorFound = false; - if ( - props.existingFargateServiceObject && - (props.existingImageObject || - props.ecrImageVersion || - props.containerDefinitionProps || - props.fargateTaskDefinitionProps || - props.ecrRepositoryArn || - props.fargateServiceProps || - props.clusterProps) - ) { + if (CheckForConflictingServiceProps(props)) { errorFound = true; errorMessages += "If you provide an existingFargateServiceObject, you cannot provide any props defining a new service\n"; @@ -290,6 +281,24 @@ export function CheckFargateProps(props: any) { } } +/** + * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. + */ +export function CheckForConflictingServiceProps(props: any): boolean { + if (props.existingFargateServiceObject && + (props.existingImageObject || + props.ecrImageVersion || + props.containerDefinitionProps || + props.fargateTaskDefinitionProps || + props.ecrRepositoryArn || + props.fargateServiceProps || + props.clusterProps) + ) { + return true; + } + return false; +} + /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ diff --git a/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts b/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts index 5e8608f29..1377e4fd0 100644 --- a/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts +++ b/source/patterns/@aws-solutions-constructs/core/lib/input-validation.ts @@ -34,10 +34,6 @@ import * as opensearch from "aws-cdk-lib/aws-opensearchservice"; import * as s3assets from "aws-cdk-lib/aws-s3-assets"; export interface VerifiedProps { - readonly dynamoTableProps?: dynamodb.TableProps, - readonly existingTableObj?: dynamodb.Table, - readonly existingTableInterface?: dynamodb.ITable, - readonly existingStreamObj?: kinesis.Stream; readonly kinesisStreamProps?: kinesis.StreamProps, @@ -56,15 +52,14 @@ export interface VerifiedProps { readonly existingBucketInterface?: s3.IBucket, readonly bucketProps?: s3.BucketProps, - readonly topicProps?: sns.TopicProps, - readonly existingTopicObj?: sns.Topic, - readonly existingSagemakerEndpointObj?: sagemaker.CfnEndpoint, readonly endpointProps?: sagemaker.CfnEndpointProps, readonly existingSecretObj?: secretsmanager.Secret; readonly secretProps?: secretsmanager.SecretProps; + readonly topicProps?: sns.TopicProps, + readonly existingVpc?: ec2.IVpc; readonly vpcProps?: ec2.VpcProps; readonly deployVpc?: boolean; @@ -100,16 +95,6 @@ export function CheckProps(propsObject: VerifiedProps | any) { errorFound = true; } - if (propsObject.dynamoTableProps && propsObject.existingTableObj) { - errorMessages += 'Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'; - errorFound = true; - } - - if (propsObject.dynamoTableProps && propsObject.existingTableInterface) { - errorMessages += 'Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'; - errorFound = true; - } - if (propsObject.existingStreamObj && propsObject.kinesisStreamProps) { errorMessages += 'Error - Either provide existingStreamObj or kinesisStreamProps, but not both.\n'; errorFound = true; @@ -160,26 +145,6 @@ export function CheckProps(propsObject: VerifiedProps | any) { errorFound = true; } - if (propsObject.existingBucketInterface && propsObject.bucketProps) { - errorMessages += 'Error - Either provide bucketProps or existingBucketInterface, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps && propsObject.existingTopicObj) { - errorMessages += 'Error - Either provide topicProps or existingTopicObj, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps?.masterKey && propsObject.encryptionKey) { - errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'; - errorFound = true; - } - - if (propsObject.topicProps?.masterKey && propsObject.encryptionKeyProps) { - errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'; - errorFound = true; - } - if (propsObject.existingSagemakerEndpointObj && propsObject.endpointProps) { errorMessages += 'Error - Either provide endpointProps or existingSagemakerEndpointObj, but not both.\n'; errorFound = true; @@ -252,7 +217,7 @@ export interface GlueProps { readonly fieldSchema?: glue.CfnTable.ColumnProperty[]; readonly existingTable?: glue.CfnTable; readonly tablePropss?: glue.CfnTableProps; - } +} export function CheckGlueProps(propsObject: GlueProps | any) { let errorMessages = ''; @@ -290,6 +255,77 @@ export function CheckGlueProps(propsObject: GlueProps | any) { } } +export interface DynamoDBProps { + readonly dynamoTableProps?: dynamodb.TableProps, + readonly existingTableObj?: dynamodb.Table, + readonly existingTableInterface?: dynamodb.ITable, +} + +export function CheckDynamoDBProps(propsObject: DynamoDBProps | any) { + let errorMessages = ''; + let errorFound = false; + + if (propsObject.dynamoTableProps && propsObject.existingTableObj) { + errorMessages += 'Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'; + errorFound = true; + } + + if (propsObject.dynamoTableProps && propsObject.existingTableInterface) { + errorMessages += 'Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} + +export interface SnsProps { + readonly topicProps?: sns.TopicProps, + readonly existingTopicObj?: sns.Topic, + readonly existingTopicObject?: sns.Topic, + readonly encryptionKey?: kms.Key, + readonly encryptionKeyProps?: kms.KeyProps +} + +export function CheckSnsProps(propsObject: SnsProps | any) { + let errorMessages = ''; + let errorFound = false; + + // FargateToSns used TopicObject instead of TopicObj - to fix would be a breaking change, so we + // must look for both here. + if (propsObject.topicProps && (propsObject.existingTopicObj || propsObject.existingTopicObject)) { + errorMessages += 'Error - Either provide topicProps or existingTopicObj, but not both.\n'; + errorFound = true; + } + + if (propsObject.topicProps?.masterKey && propsObject.encryptionKey) { + errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'; + errorFound = true; + } + + if (propsObject.topicProps?.masterKey && propsObject.encryptionKeyProps) { + errorMessages += 'Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'; + errorFound = true; + } + + if (errorFound) { + throw new Error(errorMessages); + } +} + +export interface DynamoDBProps { +} + +// export function CheckDynamoDBProps(propsObject: GlueProps | any) { +// let errorMessages = ''; +// let errorFound = false; + +// if (errorFound) { +// throw new Error(errorMessages); +// } +// } + /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ diff --git a/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts b/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts index 506b999ee..aa3f0d250 100644 --- a/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts +++ b/source/patterns/@aws-solutions-constructs/core/test/input-validation.test.ts @@ -35,22 +35,41 @@ test('Test with valid props', () => { defaults.CheckProps(props); }); +// --------------------------- +// DynamoDB Prop Tests +// --------------------------- test('Test fail DynamoDB table check', () => { const stack = new Stack(); - const props: defaults.VerifiedProps = { + const props: defaults.DynamoDBProps = { existingTableObj: new dynamodb.Table(stack, 'placeholder', defaults.DefaultTableProps), dynamoTableProps: defaults.DefaultTableProps, }; const app = () => { - defaults.CheckProps(props); + defaults.CheckDynamoDBProps(props); }; // Assertion expect(app).toThrowError('Error - Either provide existingTableObj or dynamoTableProps, but not both.\n'); }); +test('Test fail DynamoDB table check (for interface)', () => { + const stack = new Stack(); + + const props: defaults.DynamoDBProps = { + existingTableInterface: new dynamodb.Table(stack, 'placeholder', defaults.DefaultTableProps), + dynamoTableProps: defaults.DefaultTableProps, + }; + + const app = () => { + defaults.CheckDynamoDBProps(props); + }; + + // Assertion + expect(app).toThrowError('Error - Either provide existingTableInterface or dynamoTableProps, but not both.\n'); +}); + test("Test fail Lambda function check", () => { const stack = new Stack(); @@ -281,16 +300,19 @@ test('Test fail S3 check', () => { expect(app).toThrowError('Error - Either provide bucketProps or existingBucketObj, but not both.\n'); }); +// --------------------------- +// Sns Prop Tests +// --------------------------- test('Test fail SNS topic check', () => { const stack = new Stack(); - const props: defaults.VerifiedProps = { + const props: defaults.SnsProps = { topicProps: {}, existingTopicObj: new sns.Topic(stack, 'placeholder', {}) }; const app = () => { - defaults.CheckProps(props); + defaults.CheckSnsProps(props); }; // Assertion @@ -300,13 +322,13 @@ test('Test fail SNS topic check', () => { test('Test fail SNS topic check with bad topic attribute name', () => { const stack = new Stack(); - const props: defaults.VerifiedProps = { + const props: defaults.SnsProps = { topicProps: {}, existingTopicObj: new sns.Topic(stack, 'placeholder', {}) }; const app = () => { - defaults.CheckProps(props); + defaults.CheckSnsProps(props); }; // Assertion @@ -333,7 +355,7 @@ test('Test fail SNS topic check when both encryptionKey and encryptionKeyProps a test('Test fail SNS topic check when both topicProps.masterKey and encryptionKeyProps are specified', () => { const stack = new Stack(); - const props: defaults.VerifiedProps = { + const props: defaults.SnsProps = { topicProps: { masterKey: new kms.Key(stack, 'key') }, @@ -343,7 +365,7 @@ test('Test fail SNS topic check when both topicProps.masterKey and encryptionKey }; const app = () => { - defaults.CheckProps(props); + defaults.CheckSnsProps(props); }; expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKeyProps, but not both.\n'); @@ -352,7 +374,7 @@ test('Test fail SNS topic check when both topicProps.masterKey and encryptionKey test('Test fail SNS topic check when both encryptionKey and topicProps.masterKey are specified', () => { const stack = new Stack(); - const props: defaults.VerifiedProps = { + const props: defaults.SnsProps = { encryptionKey: new kms.Key(stack, 'key'), topicProps: { masterKey: new kms.Key(stack, 'otherkey') @@ -360,13 +382,17 @@ test('Test fail SNS topic check when both encryptionKey and topicProps.masterKey }; const app = () => { - defaults.CheckProps(props); + defaults.CheckSnsProps(props); }; // Assertion expect(app).toThrowError('Error - Either provide topicProps.masterKey or encryptionKey, but not both.\n'); }); +// --------------------------- +// --------------------------- +// Glue Prop Tests +// --------------------------- test('Test fail Glue job check', () => { const stack = new Stack(); @@ -463,6 +489,7 @@ test('Test missing Glue script lcoation', () => { // Assertion expect(app).toThrowError(expectedError); }); +// --------------------------- test('Test fail SageMaker endpoint check', () => { const stack = new Stack(); @@ -564,27 +591,6 @@ test('Test fail Vpc check with vpcProps', () => { expect(app).toThrowError('Error - Either provide an existingVpc or some combination of deployVpc and vpcProps, but not both.\n'); }); -test('Test fail multiple failures message', () => { - const stack = new Stack(); - - const props: defaults.VerifiedProps = { - secretProps: {}, - existingSecretObj: defaults.buildSecretsManagerSecret(stack, 'secret', {}), - topicProps: {}, - existingTopicObj: new sns.Topic(stack, 'placeholder', {}) - }; - - const app = () => { - defaults.CheckProps(props); - }; - - // Assertion - expect(app).toThrowError( - 'Error - Either provide topicProps or existingTopicObj, but not both.\n' + - 'Error - Either provide secretProps or existingSecretObj, but not both.\n' - ); -}); - test('Test fail existing log bucket and log bucket prop check', () => { const stack = new Stack();