mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
278 lines
8.2 KiB
JavaScript
Executable File
278 lines
8.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
'use strict'
|
|
|
|
require('essentials')
|
|
require('log-node')()
|
|
|
|
const log = require('log').get('serverless')
|
|
const awsRequest = require('@serverless/test/aws-request')
|
|
const fsp = require('fs').promises
|
|
const path = require('path')
|
|
const CloudFormationService = require('aws-sdk').CloudFormation
|
|
const SecretsManagerService = require('aws-sdk').SecretsManager
|
|
const KafkaService = require('aws-sdk').Kafka
|
|
|
|
const {
|
|
SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
SHARED_INFRA_TESTS_ACTIVE_MQ_CREDENTIALS_NAME,
|
|
SHARED_INFRA_TESTS_RABBITMQ_CREDENTIALS_NAME,
|
|
} = require('../../../test/utils/cloudformation')
|
|
|
|
const ensureActiveMQCredentialsSecret = async () => {
|
|
const ssmMqCredentials = {
|
|
username: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_USER,
|
|
password: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_PASSWORD,
|
|
}
|
|
log.notice('Creating SecretsManager ActiveMQ Credentials secret...')
|
|
try {
|
|
await awsRequest(SecretsManagerService, 'createSecret', {
|
|
Name: SHARED_INFRA_TESTS_ACTIVE_MQ_CREDENTIALS_NAME,
|
|
SecretString: JSON.stringify(ssmMqCredentials),
|
|
})
|
|
} catch (e) {
|
|
if (!e.code === 'ResourceExistsException') {
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
|
|
const ensureRabbitMQCredentialsSecret = async () => {
|
|
const ssmMqCredentials = {
|
|
username: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_USER,
|
|
password: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_PASSWORD,
|
|
}
|
|
log.notice('Creating SecretsManager RabbitMQ Credentials secret...')
|
|
try {
|
|
await awsRequest(SecretsManagerService, 'createSecret', {
|
|
Name: SHARED_INFRA_TESTS_RABBITMQ_CREDENTIALS_NAME,
|
|
SecretString: JSON.stringify(ssmMqCredentials),
|
|
})
|
|
} catch (e) {
|
|
if (!e.code === 'ResourceExistsException') {
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
|
|
const activeMqBrokerName = 'integration-tests-activemq-broker'
|
|
const rabbitMqBrokerName = 'integration-tests-rabbitmq-broker'
|
|
|
|
async function handleInfrastructureCreation() {
|
|
const [cfnTemplate, kafkaServerProperties] = await Promise.all([
|
|
fsp.readFile(path.join(__dirname, 'cloudformation.yml'), 'utf8'),
|
|
fsp.readFile(path.join(__dirname, 'kafka.server.properties')),
|
|
])
|
|
|
|
await ensureActiveMQCredentialsSecret()
|
|
await ensureRabbitMQCredentialsSecret()
|
|
|
|
const clusterName = 'integration-tests-msk-cluster'
|
|
const clusterConfName = 'integration-tests-msk-cluster-configuration'
|
|
|
|
log.notice('Creating MSK Cluster configuration...')
|
|
const clusterConfResponse = await awsRequest(
|
|
KafkaService,
|
|
'createConfiguration',
|
|
{
|
|
Name: clusterConfName,
|
|
ServerProperties: kafkaServerProperties,
|
|
KafkaVersions: ['2.2.1'],
|
|
},
|
|
)
|
|
|
|
const clusterConfigurationArn = clusterConfResponse.Arn
|
|
const clusterConfigurationRevision =
|
|
clusterConfResponse.LatestRevision.Revision.toString()
|
|
|
|
log.notice('Deploying integration tests CloudFormation stack...')
|
|
await awsRequest(CloudFormationService, 'createStack', {
|
|
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
TemplateBody: cfnTemplate,
|
|
Parameters: [
|
|
{ ParameterKey: 'ClusterName', ParameterValue: clusterName },
|
|
{
|
|
ParameterKey: 'ActiveMQBrokerName',
|
|
ParameterValue: activeMqBrokerName,
|
|
},
|
|
{
|
|
ParameterKey: 'ActiveMQUser',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_USER,
|
|
},
|
|
{
|
|
ParameterKey: 'ActiveMQPassword',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_PASSWORD,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQBrokerName',
|
|
ParameterValue: rabbitMqBrokerName,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQUser',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_USER,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQPassword',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_PASSWORD,
|
|
},
|
|
{
|
|
ParameterKey: 'ClusterConfigurationArn',
|
|
ParameterValue: clusterConfigurationArn,
|
|
},
|
|
{
|
|
ParameterKey: 'ClusterConfigurationRevision',
|
|
ParameterValue: clusterConfigurationRevision,
|
|
},
|
|
],
|
|
})
|
|
|
|
await awsRequest(CloudFormationService, 'waitFor', 'stackCreateComplete', {
|
|
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
})
|
|
log.notice('Deployed integration tests CloudFormation stack!')
|
|
}
|
|
|
|
async function handleInfrastructureUpdate() {
|
|
log.notice('Updating integration tests CloudFormation stack...')
|
|
|
|
await ensureActiveMQCredentialsSecret()
|
|
await ensureRabbitMQCredentialsSecret()
|
|
|
|
const cfnTemplate = await fsp.readFile(
|
|
path.join(__dirname, 'cloudformation.yml'),
|
|
'utf8',
|
|
)
|
|
|
|
try {
|
|
await awsRequest(CloudFormationService, 'updateStack', {
|
|
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
TemplateBody: cfnTemplate,
|
|
Parameters: [
|
|
{ ParameterKey: 'ClusterName', UsePreviousValue: true },
|
|
{
|
|
ParameterKey: 'ActiveMQBrokerName',
|
|
ParameterValue: activeMqBrokerName,
|
|
},
|
|
{
|
|
ParameterKey: 'ActiveMQUser',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_USER,
|
|
},
|
|
{
|
|
ParameterKey: 'ActiveMQPassword',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_PASSWORD,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQBrokerName',
|
|
ParameterValue: rabbitMqBrokerName,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQUser',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_USER,
|
|
},
|
|
{
|
|
ParameterKey: 'RabbitMQPassword',
|
|
ParameterValue: process.env.SLS_INTEGRATION_TESTS_RABBITMQ_PASSWORD,
|
|
},
|
|
{ ParameterKey: 'ClusterConfigurationArn', UsePreviousValue: true },
|
|
{
|
|
ParameterKey: 'ClusterConfigurationRevision',
|
|
UsePreviousValue: true,
|
|
},
|
|
],
|
|
})
|
|
} catch (e) {
|
|
if (e.message === 'No updates are to be performed.') {
|
|
log.notice(
|
|
'No changes detected. Integration tests CloudFormation stack is up to date.',
|
|
)
|
|
return
|
|
}
|
|
throw e
|
|
}
|
|
|
|
await awsRequest(CloudFormationService, 'waitFor', 'stackUpdateComplete', {
|
|
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
})
|
|
log.notice('Updated integration tests CloudFormation stack!')
|
|
}
|
|
|
|
;(async () => {
|
|
log.notice('Starting setup of integration infrastructure...')
|
|
|
|
if (!process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_USER) {
|
|
log.error(
|
|
'"SLS_INTEGRATION_TESTS_ACTIVE_MQ_USER" env variable has to be set when provisioning integration infrastructure',
|
|
)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
if (!process.env.SLS_INTEGRATION_TESTS_ACTIVE_MQ_PASSWORD) {
|
|
log.error(
|
|
'"SLS_INTEGRATION_TESTS_ACTIVE_MQ_PASSWORD" env variable has to be set when provisioning integration infrastructure',
|
|
)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
if (!process.env.SLS_INTEGRATION_TESTS_RABBITMQ_USER) {
|
|
log.error(
|
|
'"SLS_INTEGRATION_TESTS_RABBITMQ_USER" env variable has to be set when provisioning integration infrastructure',
|
|
)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
if (!process.env.SLS_INTEGRATION_TESTS_RABBITMQ_PASSWORD) {
|
|
log.error(
|
|
'"SLS_INTEGRATION_TESTS_RABBITMQ_PASSWORD" env variable has to be set when provisioning integration infrastructure',
|
|
)
|
|
process.exitCode = 1
|
|
return
|
|
}
|
|
|
|
let describeResponse
|
|
|
|
log.notice(
|
|
'Checking if integration tests CloudFormation stack already exists...',
|
|
)
|
|
try {
|
|
describeResponse = await awsRequest(
|
|
CloudFormationService,
|
|
'describeStacks',
|
|
{
|
|
StackName: SHARED_INFRA_TESTS_CLOUDFORMATION_STACK,
|
|
},
|
|
)
|
|
log.notice('Integration tests CloudFormation stack already exists')
|
|
} catch (e) {
|
|
if (e.code !== 'ValidationError') {
|
|
throw e
|
|
}
|
|
log.notice('Integration tests CloudFormation does not exist')
|
|
}
|
|
|
|
if (describeResponse) {
|
|
const stackStatus = describeResponse.Stacks[0].StackStatus
|
|
|
|
if (
|
|
[
|
|
'CREATE_COMPLETE',
|
|
'UPDATE_COMPLETE',
|
|
'UPDATE_ROLLBACK_COMPLETE',
|
|
].includes(stackStatus)
|
|
) {
|
|
await handleInfrastructureUpdate()
|
|
} else {
|
|
log.error(
|
|
`Existing stack has status: ${stackStatus} and it cannot be updated.`,
|
|
)
|
|
process.exitCode = 1
|
|
}
|
|
} else {
|
|
await handleInfrastructureCreation()
|
|
}
|
|
|
|
log.notice('Setup of integration infrastructure finished')
|
|
})()
|