mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
226 lines
7.4 KiB
JavaScript
226 lines
7.4 KiB
JavaScript
'use strict';
|
|
|
|
const BbPromise = require('bluebird');
|
|
const _ = require('lodash');
|
|
const chalk = require('chalk');
|
|
const childProcess = BbPromise.promisifyAll(require('child_process'));
|
|
const fdk = require('@serverless/fdk');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
const getLocalRootUrl = require('./utils/getLocalRootUrl');
|
|
const getLocalEmulatorFunctionConfig = require('./utils/getLocalEmulatorFunctionConfig');
|
|
const deployFunctionToLocalEmulator = require('./utils/deployFunctionToLocalEmulator');
|
|
|
|
const localEmulatorRunning = require('./utils/localEmulatorRunning');
|
|
const eventGatewayRunning = require('./utils/eventGatewayRunning');
|
|
|
|
const localEmulatorInstalled = require('./utils/localEmulatorInstalled');
|
|
const eventGatewayInstalled = require('./utils/eventGatewayInstalled');
|
|
|
|
const installLocalEmulator = require('./utils/installLocalEmulator');
|
|
const installEventGateway = require('./utils/installEventGateway');
|
|
const getLatestEventGatewayVersion = require('./utils/getLatestEventGatewayVersion');
|
|
|
|
class Run {
|
|
constructor(serverless, options) {
|
|
this.serverless = serverless;
|
|
this.options = options;
|
|
|
|
this.commands = {
|
|
run: {
|
|
usage: 'Runs the Event Gateway and the Local Emulator',
|
|
lifecycleEvents: [
|
|
'run',
|
|
],
|
|
options: {
|
|
eport: {
|
|
usage: 'The Event Gateway API port',
|
|
shortcut: 'e',
|
|
default: '4000',
|
|
},
|
|
cport: {
|
|
usage: 'The Event Gateway configuration port',
|
|
shortcut: 'e',
|
|
default: '4001',
|
|
},
|
|
lport: {
|
|
usage: 'The Local Emulator port',
|
|
shortcut: 'l',
|
|
default: '4002',
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
this.hooks = {
|
|
'run:run': () => BbPromise.bind(this)
|
|
.then(this.run),
|
|
};
|
|
}
|
|
|
|
run() {
|
|
let functionsDeployed = false;
|
|
let functionsRegistered = false;
|
|
if (!this.serverless.config.servicePath) {
|
|
throw new this.serverless.classes
|
|
.Error('This command can only run inside a service');
|
|
}
|
|
|
|
return localEmulatorRunning(getLocalRootUrl(this.options.lport))
|
|
.then(localEmulatorAlreadyRunning => {
|
|
if (localEmulatorAlreadyRunning) {
|
|
this.logServerless('Local Emulator Already Running');
|
|
functionsDeployed = true;
|
|
return this.deployFunctionsToLocalEmulator();
|
|
}
|
|
return BbPromise.resolve();
|
|
})
|
|
.then(() => eventGatewayRunning(getLocalRootUrl(this.options.cport)))
|
|
.then(eventGatewayAlreadyRunning => {
|
|
if (eventGatewayAlreadyRunning) {
|
|
functionsRegistered = true;
|
|
this.logServerless('Event Gateway Already Running');
|
|
return this.registerFunctionsToEventGateway();
|
|
}
|
|
return BbPromise.resolve();
|
|
})
|
|
.then(() => {
|
|
if (!localEmulatorInstalled()) {
|
|
this.logServerless('Installing Local Emulator...');
|
|
installLocalEmulator();
|
|
}
|
|
return BbPromise.resolve();
|
|
})
|
|
.then(() => {
|
|
if (!eventGatewayInstalled()) {
|
|
return getLatestEventGatewayVersion()
|
|
.then(version => installEventGateway(version));
|
|
}
|
|
return BbPromise.resolve();
|
|
})
|
|
.then(() => {
|
|
return new BbPromise((resolve, reject) => {
|
|
if (!functionsDeployed) {
|
|
let initialized = false;
|
|
this.logServerless('Spinning Up the Local Emulator...');
|
|
const localEmulatorChildProcess = childProcess.spawn('sle',
|
|
['--port', this.options.lport]);
|
|
|
|
localEmulatorChildProcess.stdout.on('data', chunk => {
|
|
this.logLocalEmulator(chunk.toString('utf8'));
|
|
if (!initialized) {
|
|
initialized = true;
|
|
return this.deployFunctionsToLocalEmulator();
|
|
}
|
|
return BbPromise.resolve();
|
|
});
|
|
|
|
localEmulatorChildProcess.stderr.on('data', chunk => {
|
|
this.logLocalEmulator(chunk.toString('utf8'));
|
|
});
|
|
|
|
localEmulatorChildProcess.on('close', () => resolve());
|
|
localEmulatorChildProcess.on('error', error => reject(error));
|
|
}
|
|
|
|
if (!functionsRegistered) {
|
|
let initialized = false;
|
|
const eventGatewayBinaryFilePath = path
|
|
.join(os.homedir(), '.serverless', 'event-gateway', 'event-gateway');
|
|
this.logServerless('Spinning Up the Event Gateway...');
|
|
const eventGatewayChildProcess = childProcess
|
|
.spawn(eventGatewayBinaryFilePath, ['--dev']);
|
|
|
|
eventGatewayChildProcess.stdout.on('data', chunk => {
|
|
this.logEventGateway(chunk.toString('utf8'));
|
|
});
|
|
|
|
eventGatewayChildProcess.stderr.on('data', chunk => {
|
|
this.logEventGateway(chunk.toString('utf8'));
|
|
if (!initialized) {
|
|
initialized = true;
|
|
return this.registerFunctionsToEventGateway();
|
|
}
|
|
});
|
|
|
|
eventGatewayChildProcess.on('close', () => resolve());
|
|
eventGatewayChildProcess.on('error', error => reject(error));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
deployFunctionsToLocalEmulator() {
|
|
this.logServerless('Deploying Functions to Local Emulator...');
|
|
const service = this.serverless.service;
|
|
const serviceName = service.service;
|
|
const providerConfig = service.provider;
|
|
const functionDeploymentPromises = [];
|
|
|
|
_.each(service.functions, (functionConfig,
|
|
functionName) => {
|
|
const localEmulatorFunctionConfig = getLocalEmulatorFunctionConfig(
|
|
functionConfig,
|
|
providerConfig,
|
|
this.serverless.config.servicePath);
|
|
|
|
const deployFunctionToLocalEmulatorPromise = deployFunctionToLocalEmulator(
|
|
serviceName, functionName,
|
|
localEmulatorFunctionConfig, getLocalRootUrl(this.options.lport));
|
|
functionDeploymentPromises.push(deployFunctionToLocalEmulatorPromise);
|
|
});
|
|
|
|
return BbPromise.all(functionDeploymentPromises)
|
|
.then(() => this.logServerless('Functions Deployed!'));
|
|
}
|
|
|
|
registerFunctionsToEventGateway() {
|
|
this.logServerless('Registering Functions to the Event Gateway...');
|
|
|
|
const gateway = fdk.eventGateway({
|
|
url: getLocalRootUrl(this.options.eport),
|
|
configurationUrl: getLocalRootUrl(this.options.cport),
|
|
});
|
|
const functionsArray = [];
|
|
const service = this.serverless.service;
|
|
const serviceName = service.service;
|
|
|
|
_.each(service.functions, (functionConfig,
|
|
functionName) => {
|
|
const functionId = `${serviceName}${functionName}`;
|
|
const invokeFunctionUrl = `${getLocalRootUrl(this.options.lport)
|
|
}/v0/emulator/api/invoke/${serviceName}/${functionName}`;
|
|
|
|
const functionObject = {
|
|
functionId,
|
|
provider: {
|
|
type: 'http',
|
|
url: invokeFunctionUrl,
|
|
},
|
|
};
|
|
functionsArray.push(functionObject);
|
|
});
|
|
|
|
setTimeout(() => {
|
|
return gateway.configure({ functions: functionsArray })
|
|
.then(() => this.logServerless('Functions Registered in the Event Gateway!'));
|
|
}, 3000);
|
|
|
|
}
|
|
|
|
logServerless(message) {
|
|
process.stdout.write(chalk.yellow(` Serverless | ${message}\n`));
|
|
}
|
|
|
|
logLocalEmulator(message) {
|
|
process.stdout.write(chalk.green(` Local Emulator | ${message.trim()}\n`));
|
|
}
|
|
|
|
logEventGateway(message) {
|
|
process.stdout.write(chalk.blue(` Event Gateway | ${message.trim()}\n`));
|
|
}
|
|
}
|
|
|
|
module.exports = Run;
|