mirror of
https://github.com/serverless/serverless.git
synced 2025-12-08 19:46:03 +00:00
239 lines
8.0 KiB
JavaScript
Executable File
239 lines
8.0 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');
|
|
})();
|