UNPKG

@aws-solutions-constructs/core

Version:
787 lines 103 kB
"use strict"; /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * with the License. A copy of the License is located at * * http://www.apache.org/licenses/LICENSE-2.0 * * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * and limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); const sqs_helper_1 = require("../lib/sqs-helper"); const step_function_helper_1 = require("../lib/step-function-helper"); const dynamodb_table_helper_1 = require("../lib/dynamodb-table-helper"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const defaults = require("../"); const lambda = require("aws-cdk-lib/aws-lambda"); const s3 = require("aws-cdk-lib/aws-s3"); const assertions_1 = require("aws-cdk-lib/assertions"); const aws_logs_1 = require("aws-cdk-lib/aws-logs"); // ================================= // Test sources and targets generation // ================================= test('Create a default SQS Source', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildQueueResponse = (0, sqs_helper_1.buildQueue)(stack, 'test-queue', {}); const sqsSource = defaults.CreateSqsSource(buildQueueResponse.queue); expect(sqsSource.sourceArn).toEqual(buildQueueResponse.queue.queueArn); expect(Object.keys(sqsSource.sourceParameters).length).toEqual(0); // best we can do here, confirm values when we instantiate the actual pipe expect(sqsSource.sourcePolicy.statementCount).toEqual(1); assertions_1.Template.fromStack(stack); }); test('Create an SQS Source with overrides', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildQueueResponse = (0, sqs_helper_1.buildQueue)(stack, 'test-queue', {}); const sqsSource = defaults.CreateSqsSource(buildQueueResponse.queue, { sqsQueueParameters: { batchSize: 123, }, }); expect(sqsSource.sourceArn).toEqual(buildQueueResponse.queue.queueArn); // Because sqsQueueParameters type include 'IResolvable |', we need to extract the property this way const batchSizeProp = sqsSource.sourceParameters.sqsQueueParameters.batchSize; expect(batchSizeProp).toEqual(123); // best we can do here, confirm values when we instantiate the actual pipe expect(sqsSource.sourcePolicy.statementCount).toEqual(1); }); test('Create a default DDB Streams Source', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildTableResponse = (0, dynamodb_table_helper_1.buildDynamoDBTableWithStream)(stack, {}); const tableSource = defaults.CreateDynamoDBStreamsSource(stack, { table: buildTableResponse.tableObject }); expect(tableSource.sourceArn).toEqual(buildTableResponse.tableObject?.tableStreamArn); expect(Object.keys(tableSource.sourceParameters).length).toEqual(1); expect(tableSource.sourcePolicy.statementCount).toEqual(2); expect(tableSource.dlq).toBeDefined(); const streamParamters = tableSource.sourceParameters.dynamoDbStreamParameters; expect(streamParamters.deadLetterConfig).toBeDefined(); }); test('Confirm that we use custom DLQ props', () => { const queueName = 'something-unique-asdf'; // Stack const stack = new aws_cdk_lib_1.Stack(); const buildTableResponse = (0, dynamodb_table_helper_1.buildDynamoDBTableWithStream)(stack, {}); defaults.CreateDynamoDBStreamsSource(stack, { table: buildTableResponse.tableObject, sqsDlqQueueProps: { queueName, } }); const template = assertions_1.Template.fromStack(stack); template.hasResourceProperties("AWS::SQS::Queue", { QueueName: queueName }); }); test('Create DDB Streams Source with no DLQ', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildTableResponse = (0, dynamodb_table_helper_1.buildDynamoDBTableWithStream)(stack, {}); const tableSource = defaults.CreateDynamoDBStreamsSource(stack, { table: buildTableResponse.tableObject, deploySqsDlqQueue: false }); expect(tableSource.sourceArn).toEqual(buildTableResponse.tableObject?.tableStreamArn); expect(Object.keys(tableSource.sourceParameters).length).toEqual(1); expect(tableSource.sourcePolicy.statementCount).toEqual(1); expect(tableSource.dlq).toBeUndefined(); const streamParamters = tableSource.sourceParameters.dynamoDbStreamParameters; expect(streamParamters.maximumRetryAttempts).toBeUndefined(); expect(streamParamters.deadLetterConfig).toBeUndefined(); expect(streamParamters.startingPosition).toBeDefined(); }); test('Create an DDB Streams Source with overrides', () => { const batchSizeValue = 4642; // Stack const stack = new aws_cdk_lib_1.Stack(); const buildTableResponse = (0, dynamodb_table_helper_1.buildDynamoDBTableWithStream)(stack, {}); const tableSource = defaults.CreateDynamoDBStreamsSource(stack, { table: buildTableResponse.tableObject, clientProps: { dynamoDbStreamParameters: { startingPosition: 'LATEST', batchSize: batchSizeValue } } }); expect(tableSource.sourceArn).toEqual(buildTableResponse.tableObject?.tableStreamArn); // Because sqsQueueParameters type include 'IResolvable |', we need to extract the property this way const batchSizeProp = tableSource.sourceParameters.dynamoDbStreamParameters.batchSize; expect(batchSizeProp).toEqual(batchSizeValue); // best we can do here, confirm values when we instantiate the actual pipe expect(tableSource.sourcePolicy.statementCount).toEqual(2); const streamParamters = tableSource.sourceParameters.dynamoDbStreamParameters; expect(streamParamters.maximumRetryAttempts).toEqual(3); expect(streamParamters.deadLetterConfig).toBeDefined(); expect(streamParamters.startingPosition).toBeDefined(); }); test('Create a default Step Functions Target', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildStateMachineResponse = (0, step_function_helper_1.buildStateMachine)(stack, 'test-state-machine', { stateMachineProps: { definitionBody: defaults.CreateTestStateMachineDefinitionBody(stack, 'stub-state-machine') } }); const stateMachineTarget = defaults.CreateStateMachineTarget(buildStateMachineResponse.stateMachine); expect(stateMachineTarget.targetArn).toEqual(buildStateMachineResponse.stateMachine.stateMachineArn); expect(stateMachineTarget.targetParameters.stepFunctionStateMachineParameters).toBeDefined(); const invocationType = stateMachineTarget.targetParameters.stepFunctionStateMachineParameters.invocationType; expect(invocationType).toEqual('FIRE_AND_FORGET'); expect(Object.keys(stateMachineTarget.targetParameters).length).toEqual(1); // best we can do here, confirm values when we instantiate the actual pipe expect(stateMachineTarget.targetPolicy.statementCount).toEqual(1); assertions_1.Template.fromStack(stack); }); test('Create a Step Functions Target with overrides', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildStateMachineResponse = (0, step_function_helper_1.buildStateMachine)(stack, 'test-state-machine', { stateMachineProps: { definitionBody: defaults.CreateTestStateMachineDefinitionBody(stack, 'stub-state-machine') } }); const stateMachineTarget = defaults.CreateStateMachineTarget(buildStateMachineResponse.stateMachine, { stepFunctionStateMachineParameters: { invocationType: 'REQUEST_RESPONSE' } }); expect(stateMachineTarget.targetArn).toEqual(buildStateMachineResponse.stateMachine.stateMachineArn); expect(stateMachineTarget.targetParameters.stepFunctionStateMachineParameters).toBeDefined(); const invocationType = stateMachineTarget.targetParameters.stepFunctionStateMachineParameters.invocationType; expect(invocationType).toEqual('REQUEST_RESPONSE'); expect(Object.keys(stateMachineTarget.targetParameters).length).toEqual(1); // best we can do here, confirm values when we instantiate the actual pipe expect(stateMachineTarget.targetPolicy.statementCount).toEqual(1); }); test('Check for error when DLQ is off but max constraint set', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const buildTableResponse = (0, dynamodb_table_helper_1.buildDynamoDBTableWithStream)(stack, {}); const app = () => { defaults.CreateDynamoDBStreamsSource(stack, { clientProps: { dynamoDbStreamParameters: { startingPosition: 'LATEST', maximumRecordAgeInSeconds: 100 } }, table: buildTableResponse.tableObject, deploySqsDlqQueue: false }); }; // Assertion expect(app).toThrowError('ERROR - retry and record age constraints cannot be specified with no DLQ\n'); }); // ================================= // Test pipe creation // ================================= test('Create a default pipe', () => { const prerequisiteId = 'alldefault'; const pipeId = 'defaultpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, clientProps: {} }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); }); test('Create a pipe with overrides', () => { const prerequisiteId = 'overridestest'; const pipeId = 'overridespipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const testDescription = 'test-description'; const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, clientProps: { description: testDescription } }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); // The description is unique to this test, so check it here template.hasResourceProperties('AWS::Pipes::Pipe', { Description: testDescription }); }); test('Create a pipe with a filter', () => { const prerequisiteId = 'filtertest'; const pipeId = 'filterpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const testFilterPattern = `{ "body": { "state": ["open"] } }`; const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, clientProps: { sourceParameters: { filterCriteria: { filters: [{ pattern: testFilterPattern }], }, } }, }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); // SourceParameters is unique to this test, so check it here template.hasResourceProperties('AWS::Pipes::Pipe', { SourceParameters: { FilterCriteria: { Filters: [ { Pattern: testFilterPattern } ] } } }); }); test('Create a pipe with Lambda function enrichment', () => { const prerequisiteId = 'lambdaenrichtest'; const pipeId = 'lambdaenrichpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const enrichmentFunction = new lambda.Function(stack, 'enrichment-function', { code: lambda.Code.fromAsset(`${__dirname}/lambda-test`), handler: "index.handler", runtime: lambda.Runtime.NODEJS_20_X, }); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, enrichmentFunction }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckLogGroup(template); // Enrichment is unique to this test so check it here template.hasResourceProperties('AWS::Pipes::Pipe', { Enrichment: { "Fn::GetAtt": [ assertions_1.Match.stringLikeRegexp('enrichmentfunction.*'), "Arn" ] }, }); // This checks for everything but enrichment CheckPipeRole(template, prerequisiteId); // This checks for enrichment permissions template.hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { Action: "lambda:InvokeFunction", Effect: "Allow", Resource: { "Fn::GetAtt": [ assertions_1.Match.stringLikeRegexp('enrichmentfunction.*'), "Arn" ] } } ], Version: "2012-10-17" }, PolicyName: assertions_1.Match.stringLikeRegexp(`enrichmentpolicy${pipeId}.*`), Roles: [ { Ref: assertions_1.Match.stringLikeRegexp(`PipeRole${pipeId}.*`) } ] }); }); test('Create a pipe with state machine enrichment', () => { const prerequisiteId = 'smenrichtest'; const pipeId = 'smenrichpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const enrichmentStateMachine = defaults.CreateTestStateMachine(stack, 'state-machine-enrichment'); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, enrichmentStateMachine }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); // Look for additional enrichment permision template.hasResourceProperties('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { // This won't run if we actually launched it as the enrichmentStateMachine is not EXPRESS Action: "states:StartSyncExecution", Effect: "Allow", Resource: { Ref: assertions_1.Match.stringLikeRegexp('statemachineenrichment.*'), } } ], Version: "2012-10-17" }, PolicyName: assertions_1.Match.stringLikeRegexp(`enrichmentpolicy${pipeId}.*`), Roles: [ { Ref: assertions_1.Match.stringLikeRegexp(`PipeRole${pipeId}.*`) } ] }); template.hasResourceProperties('AWS::Pipes::Pipe', { Enrichment: { Ref: assertions_1.Match.stringLikeRegexp("statemachineenrichment.*") }, }); }); test('Provide replacement LogConfiguration', () => { const prerequisiteId = 'logconfigtest'; const pipeId = 'logconfigpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const customLogConfiguration = { s3LogDestination: { bucketName: new s3.Bucket(stack, 'test').bucketName, }, level: defaults.PipesLogLevel.ERROR }; const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, clientProps: { logConfiguration: customLogConfiguration } }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); CheckPipeSourceAndTarget(template, prerequisiteId); template.hasResourceProperties('AWS::Pipes::Pipe', { LogConfiguration: { Level: "ERROR", S3LogDestination: { BucketName: { Ref: assertions_1.Match.stringLikeRegexp("test.*") } } } }); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeRole(template, prerequisiteId); }); test('Override the default log level', () => { const prerequisiteId = 'loglevelttest'; const pipeId = 'loglevelpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, logLevel: defaults.PipesLogLevel.ERROR }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); // Level is unique to this test template.hasResourceProperties('AWS::Pipes::Pipe', { LogConfiguration: { Level: defaults.PipesLogLevel.ERROR, } }); }); test('Test no logging', () => { const prerequisiteId = 'nologs'; const pipeId = 'testpipe'; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, logLevel: defaults.PipesLogLevel.OFF }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeSourceAndTarget(template, prerequisiteId); CheckPipeRole(template, prerequisiteId); // One log group for the state machine, none for the pipe template.resourceCountIs('AWS::Logs::LogGroup', 1); }); test('Override a subset of SQS source paramters', () => { const prerequisiteId = 'srcparamtest'; const pipeId = 'srcparampipe'; const testBatchSize = 7; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, clientProps: { sourceParameters: { sqsQueueParameters: { batchSize: testBatchSize, } } } }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); template.resourceCountIs('AWS::Pipes::Pipe', 1); template.hasResourceProperties('AWS::Pipes::Pipe', { SourceParameters: { SqsQueueParameters: { BatchSize: testBatchSize } }, }); }); test('Provide pipeLogProps', () => { const prerequisiteId = 'pipelogpropstest'; const pipeId = 'pipelogpropspipe'; // While this is an enum we need to use, in the template // it is converted to days, in this case 120 const testRetention = aws_logs_1.RetentionDays.FOUR_MONTHS; // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, prerequisiteId); const pipeResponse = defaults.BuildPipe(stack, pipeId, { source: prerequisites.source, target: prerequisites.target, pipeLogProps: { retention: testRetention } }); CheckPipeResponseProperties(pipeResponse, prerequisites); const template = assertions_1.Template.fromStack(stack); template.resourceCountIs('AWS::Pipes::Pipe', 1); CheckPipeResource(template, pipeId, prerequisiteId); CheckPipeRole(template, prerequisiteId); CheckLogGroup(template); CheckPipeLogConfiguration(template, pipeId); // Look for additional property we passed in pipeLogProps template.hasResourceProperties('AWS::Logs::LogGroup', { RetentionInDays: 120, }); }); test('Check for error when providing source in CfnProps', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, clientProps: { source: prerequisites.source.sourceArn } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify source, target, roleArn, or enrichment'); }); test('Check for error when providing target in CfnProps', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, clientProps: { target: prerequisites.target.targetArn, } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify source, target, roleArn, or enrichment'); }); test('Check for error when providing a roleArn', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, clientProps: { roleArn: "some-arn", } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify source, target, roleArn, or enrichment'); }); test('Check for error when providing enrichment', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, clientProps: { enrichment: "functionArn", } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify source, target, roleArn, or enrichment'); }); test('Check for error when log level and log configuration are both provided', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, logLevel: defaults.PipesLogLevel.ERROR, clientProps: { logConfiguration: { some: "object" }, } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify logLevel and logConfiguration'); }); test('Check for error when pipeLogProps and log configuration are both provided', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, pipeLogProps: { logGroupName: "anyvalue" }, clientProps: { logConfiguration: { some: "object" }, } }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify pipeLogProps and logConfiguration'); }); test('Check for error when enrichmentFunction and enrichmentStateMachine are both provided', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, enrichmentFunction: { place: "holder" }, enrichmentStateMachine: { place: "holder" } }); }; // Assertion expect(app).toThrowError('ERROR - Only one of enrichmentFunction or enrichmentStateMachine can be provided'); }); test('Check for error when pipeLogProps and log level is set to OFF', () => { // Stack const stack = new aws_cdk_lib_1.Stack(); const prerequisites = CreatePrerequisites(stack, 'log-level-test'); const app = () => { defaults.BuildPipe(stack, 'test-pipe', { source: prerequisites.source, target: prerequisites.target, logLevel: defaults.PipesLogLevel.OFF, pipeLogProps: { logGroupName: "anyvalue" }, }); }; // Assertion expect(app).toThrowError('ERROR - BuildPipeProps cannot specify pipeLogProps and log level OFF'); }); test('Test all of CheckPipesProps', () => { const app = () => { defaults.CheckPipesProps({ pipesProps: { source: "value" }, }); }; // Assertion expect(app).toThrowError('Do not set source in pipesProps. It is set by the construct.\n'); const appTwo = () => { defaults.CheckPipesProps({ pipesProps: { target: "value" }, }); }; // Assertion expect(appTwo).toThrowError('Do not set target in pipesProps. It is set by the construct.\n'); }); function CreatePrerequisites(scope, id) { const buildQueueResponse = (0, sqs_helper_1.buildQueue)(scope, `${id}-source-queue`, {}); const sqsSource = defaults.CreateSqsSource(buildQueueResponse.queue); const buildStateMachineResponse = (0, step_function_helper_1.buildStateMachine)(scope, `${id}-target-state-machine`, { stateMachineProps: { definitionBody: defaults.CreateTestStateMachineDefinitionBody(scope, `${id}-steps`) } }); const stateMachineTarget = defaults.CreateStateMachineTarget(buildStateMachineResponse.stateMachine, { stepFunctionStateMachineParameters: { invocationType: 'REQUEST_RESPONSE' } }); return { source: sqsSource, target: stateMachineTarget }; } // ============================== // Shared functions that check default settings // ============================== function CheckPipeResponseProperties(pipeResponse, prerequisites) { expect(pipeResponse.pipe).toBeDefined(); expect(pipeResponse.pipe.source).toEqual(prerequisites.source.sourceArn); expect(pipeResponse.pipe.target).toEqual(prerequisites.target.targetArn); expect(pipeResponse.pipeRole).toBeDefined(); expect(pipeResponse.pipeRole.node).toBeDefined(); } function CheckPipeResource(template, pipeId, prerequisiteId) { CheckPipeSourceAndTarget(template, prerequisiteId); CheckPipeLogConfiguration(template, pipeId); } function CheckPipeSourceAndTarget(template, prerequisiteId) { template.hasResourceProperties('AWS::Pipes::Pipe', { Source: { "Fn::GetAtt": [ assertions_1.Match.stringLikeRegexp(`${prerequisiteId}sourcequeue.*`), "Arn" ] }, Target: { Ref: assertions_1.Match.stringLikeRegexp(`StateMachine${prerequisiteId}targetstatemachine.*`), }, }); } function CheckPipeLogConfiguration(template, pipeId) { template.hasResourceProperties('AWS::Pipes::Pipe', { LogConfiguration: { CloudwatchLogsLogDestination: { LogGroupArn: { "Fn::GetAtt": [ assertions_1.Match.stringLikeRegexp(`LogGroup${pipeId}.*`), "Arn" ] } } } }); } function CheckPipeRole(template, prerequisiteId) { template.hasResourceProperties('AWS::IAM::Role', { AssumeRolePolicyDocument: { Statement: [ { Action: "sts:AssumeRole", Effect: "Allow", Principal: { Service: "pipes.amazonaws.com" } } ], Version: "2012-10-17" }, Policies: [ { PolicyDocument: { Statement: [ { Action: [ "sqs:ReceiveMessage", "sqs:DeleteMessage", "sqs:GetQueueAttributes" ], Effect: "Allow", Resource: { "Fn::GetAtt": [ assertions_1.Match.stringLikeRegexp(`${prerequisiteId}sourcequeue.*`), "Arn" ] } } ], Version: "2012-10-17" }, PolicyName: "sourcePolicy" }, { PolicyDocument: { Statement: [ { Action: "states:StartExecution", Effect: "Allow", Resource: { Ref: assertions_1.Match.stringLikeRegexp(`StateMachine${prerequisiteId}targetstatemachine.*`) } } ], Version: "2012-10-17" }, PolicyName: "targetPolicy" } ] }); } function CheckLogGroup(template) { template.hasResourceProperties('AWS::Logs::LogGroup', { LogGroupName: { "Fn::Join": [ "", [ assertions_1.Match.stringLikeRegexp('/aws/vendedlogs/pipes/constructs'), { "Fn::Select": [ 2, assertions_1.Match.anyValue() ] } ] ] }, }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZXMtaGVscGVyLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwaXBlcy1oZWxwZXIudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBRUgsa0RBQStDO0FBQy9DLHNFQUFnRTtBQUNoRSx3RUFBNEU7QUFDNUUsNkNBQW9DO0FBQ3BDLGdDQUFnQztBQUVoQyxpREFBaUQ7QUFFakQseUNBQXlDO0FBQ3pDLHVEQUF5RDtBQUN6RCxtREFBcUQ7QUFFckQsb0NBQW9DO0FBQ3BDLHNDQUFzQztBQUN0QyxvQ0FBb0M7QUFFcEMsSUFBSSxDQUFDLDZCQUE2QixFQUFFLEdBQUcsRUFBRTtJQUN2QyxRQUFRO0lBQ1IsTUFBTSxLQUFLLEdBQUcsSUFBSSxtQkFBSyxFQUFFLENBQUM7SUFFMUIsTUFBTSxrQkFBa0IsR0FBRyxJQUFBLHVCQUFVLEVBQUMsS0FBSyxFQUFFLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMvRCxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXJFLE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEUsMEVBQTBFO0lBQzFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6RCxxQkFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM1QixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxxQ0FBcUMsRUFBRSxHQUFH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