Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce test based on setup/teardown infrastructure
- Loading branch information
Showing
9 changed files
with
278 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
'use strict'; | ||
|
||
const awsRequest = require('@serverless/test/aws-request'); | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { SHARED_INFRA_TESTS_CLOUDFORMATION_STACK } = require('../../test/utils/cludformation'); | ||
|
||
(async () => { | ||
process.stdout.write('Starting setup of integration infrastructure...\n'); | ||
const cfnTemplate = fs.readFileSync(path.join(__dirname, 'cloudformation.yml'), 'utf8'); | ||
const kafkaServerProperties = fs.readFileSync(path.join(__dirname, 'kafka.server.properties')); | ||
|
||
process.stdout.write('Checking if integration tests CloudFormation stack already exists...\n'); | ||
try { | ||
await awsRequest('CloudFormation', 'describeStacks', { | ||
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
}); | ||
process.stdout.write('Integration tests CloudFormation stack already exists. Quitting.\n'); | ||
return; | ||
} catch (e) { | ||
process.stdout.write('Integration tests CloudFormation does not exist. Continuing.\n'); | ||
} | ||
|
||
const clusterName = 'integration-tests-msk-cluster'; | ||
const clusterConfName = 'integration-tests-msk-cluster-configuration'; | ||
|
||
process.stdout.write('Creating MSK Cluster configuration...\n'); | ||
let clusterConfResponse; | ||
try { | ||
clusterConfResponse = await awsRequest('Kafka', 'createConfiguration', { | ||
Name: clusterConfName, | ||
ServerProperties: kafkaServerProperties, | ||
KafkaVersions: ['2.2.1'], | ||
}); | ||
} catch (e) { | ||
process.stdout.write( | ||
`Error: ${e} while trying to create MSK Cluster configuration. Quitting. \n` | ||
); | ||
return; | ||
} | ||
|
||
const clusterConfigurationArn = clusterConfResponse.Arn; | ||
const clusterConfigurationRevision = clusterConfResponse.LatestRevision.Revision.toString(); | ||
|
||
process.stdout.write('Deploying integration tests CloudFormation stack...\n'); | ||
await awsRequest('CloudFormation', 'createStack', { | ||
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
TemplateBody: cfnTemplate, | ||
Parameters: [ | ||
{ ParameterKey: 'ClusterName', ParameterValue: clusterName }, | ||
{ ParameterKey: 'ClusterConfigurationArn', ParameterValue: clusterConfigurationArn }, | ||
{ | ||
ParameterKey: 'ClusterConfigurationRevision', | ||
ParameterValue: clusterConfigurationRevision, | ||
}, | ||
], | ||
}); | ||
|
||
await awsRequest('CloudFormation', 'waitFor', 'stackCreateComplete', { | ||
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
}); | ||
process.stdout.write('Deployed integration tests CloudFormation stack!\n'); | ||
process.stdout.write('Setup of integration infrastructure finished\n'); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
'use strict'; | ||
|
||
const awsRequest = require('@serverless/test/aws-request'); | ||
const { | ||
SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
getDependencyStackOutputMap, | ||
} = require('../../test/utils/cludformation'); | ||
|
||
(async () => { | ||
process.stdout.write('Starting teardown of integration infrastructure...\n'); | ||
const describeClustersResponse = await awsRequest('Kafka', 'listClusters'); | ||
const clusterConfArn = | ||
describeClustersResponse.ClusterInfoList[0].CurrentBrokerSoftwareInfo.ConfigurationArn; | ||
|
||
const outputMap = await getDependencyStackOutputMap(); | ||
|
||
process.stdout.write('Removing leftover ENI...\n'); | ||
const describeResponse = await awsRequest('EC2', 'describeNetworkInterfaces', { | ||
Filters: [ | ||
{ | ||
Name: 'vpc-id', | ||
Values: [outputMap.VPC], | ||
}, | ||
{ | ||
Name: 'status', | ||
Values: ['available'], | ||
}, | ||
], | ||
}); | ||
try { | ||
await Promise.all( | ||
describeResponse.NetworkInterfaces.map(networkInterface => | ||
awsRequest('EC2', 'deleteNetworkInterface', { | ||
NetworkInterfaceId: networkInterface.NetworkInterfaceId, | ||
}) | ||
) | ||
); | ||
} catch (e) { | ||
process.stdout.write(`Error: ${e} while trying to remove leftover ENIs\n`); | ||
} | ||
process.stdout.write('Removing integration tests CloudFormation stack...\n'); | ||
await awsRequest('CloudFormation', 'deleteStack', { | ||
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
}); | ||
await awsRequest('CloudFormation', 'waitFor', 'stackDeleteComplete', { | ||
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK, | ||
}); | ||
process.stdout.write('Removed integration tests CloudFormation stack!\n'); | ||
process.stdout.write('Removing MSK Cluster configuration...\n'); | ||
await awsRequest('Kafka', 'deleteConfiguration', { | ||
Arn: clusterConfArn, | ||
}); | ||
process.stdout.write('Removed MSK Cluster configuration\n'); | ||
process.stdout.write('Teardown of integration infrastructure finished\n'); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
'use strict'; | ||
|
||
const { expect } = require('chai'); | ||
const log = require('log').get('serverless:test'); | ||
const fixtures = require('../fixtures'); | ||
const { confirmCloudWatchLogs } = require('../utils/misc'); | ||
const { | ||
isDependencyStackAvailable, | ||
getDependencyStackOutputMap, | ||
} = require('../utils/cludformation'); | ||
|
||
const awsRequest = require('@serverless/test/aws-request'); | ||
const crypto = require('crypto'); | ||
const { deployService, removeService } = require('../utils/integration'); | ||
|
||
describe('AWS - MSK Integration Test', function() { | ||
this.timeout(1000 * 60 * 100); // Involves time-taking deploys | ||
let stackName; | ||
let servicePath; | ||
const stage = 'dev'; | ||
|
||
const topicName = `msk-topic-${crypto.randomBytes(8).toString('hex')}`; | ||
|
||
before(async function beforeHook() { | ||
const isDepsStackAvailable = await isDependencyStackAvailable(); | ||
if (!isDepsStackAvailable) { | ||
log.notice( | ||
'CloudFormation stack with integration test dependencies not found. Skipping test.' | ||
); | ||
this.skip(); | ||
} | ||
|
||
const outputMap = await getDependencyStackOutputMap(); | ||
|
||
log.notice('Getting MSK Boostrap Brokers URLs...'); | ||
const getBootstrapBrokersResponse = await awsRequest('Kafka', 'getBootstrapBrokers', { | ||
ClusterArn: outputMap.MSKCluster, | ||
}); | ||
const brokerUrls = getBootstrapBrokersResponse.BootstrapBrokerStringTls; | ||
|
||
const serviceData = await fixtures.setup('functionMsk', { | ||
configExt: { | ||
functions: { | ||
producer: { | ||
vpc: { | ||
subnetIds: [outputMap.PrivateSubnetA], | ||
securityGroupIds: [outputMap.SecurityGroup], | ||
}, | ||
environment: { | ||
TOPIC_NAME: topicName, | ||
BROKER_URLS: brokerUrls, | ||
}, | ||
}, | ||
consumer: { | ||
events: [ | ||
{ | ||
msk: { | ||
arn: outputMap.MSKCluster, | ||
topic: topicName, | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
({ servicePath } = serviceData); | ||
|
||
const serviceName = serviceData.serviceConfig.service; | ||
stackName = `${serviceName}-${stage}`; | ||
log.notice(`Deploying "${stackName}" service...`); | ||
await deployService(servicePath); | ||
}); | ||
|
||
after(async () => { | ||
if (servicePath) { | ||
log.notice('Removing service...'); | ||
await removeService(servicePath); | ||
} | ||
}); | ||
|
||
it('correctly processes messages from MSK topic', async () => { | ||
const functionName = 'consumer'; | ||
const message = 'Hello from MSK Integration test!'; | ||
|
||
return confirmCloudWatchLogs( | ||
`/aws/lambda/${stackName}-${functionName}`, | ||
async () => | ||
await awsRequest('Lambda', 'invoke', { | ||
FunctionName: `${stackName}-producer`, | ||
InvocationType: 'RequestResponse', | ||
}), | ||
{ timeout: 120 * 1000 } | ||
).then(events => { | ||
const logs = events.reduce((data, event) => data + event.message, ''); | ||
expect(logs).to.include(functionName); | ||
expect(logs).to.include(message); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.