serverless-offline-elasticmq-localhost
Version:
Serverless Framework Plugin to download and run ElasticMQ
204 lines (199 loc) • 8.45 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
const child_process_1 = require("child_process");
const path_1 = require("path");
const fs_1 = require("fs");
const stringio_1 = require("@rauschma/stringio");
const https = __importStar(require("https"));
const MQ_LOCAL_PATH = (0, path_1.join)(__dirname, "../bin");
const ElasticMQLatestVersion = "1.5.7";
class ServerlessOfflineElasticMqPlugin {
constructor(serverless) {
var _a, _b;
this.serverless = serverless;
this.mqInstances = {};
this.getJarFileName = (elasticMqVersion) => {
return `elasticmq-server-${elasticMqVersion}.jar`;
};
this.downloadElasticMqIfNecessary = async () => {
const elasticMqVersion = this.elasticMqConfig.version || ElasticMQLatestVersion;
if (!elasticMqVersion) {
throw new Error("The property custom.elasticmq.version is mandatory.");
}
const elasticMqServerJarName = this.getJarFileName(elasticMqVersion);
if (this.isJarFilePresent(elasticMqServerJarName)) {
return;
}
const elasticMqVersionUrl = `https://s3-eu-west-1.amazonaws.com/softwaremill-public/elasticmq-server-${elasticMqVersion}.jar`;
const filePath = `${MQ_LOCAL_PATH}/${elasticMqServerJarName}`;
const file = (0, fs_1.createWriteStream)(filePath);
return new Promise((resolve, reject) => {
https
.get(elasticMqVersionUrl, (response) => {
response.pipe(file);
file.on("finish", () => {
file.close();
this.serverless.cli.log(`ElasticMq version ${elasticMqVersion} downloaded as ${elasticMqServerJarName}`);
resolve();
});
})
.on("error", (err) => {
fs_1.promises.unlink(filePath);
this.serverless.cli.log(`Error downloading ElasticMq version ${elasticMqVersion}: ${err.message}`);
reject();
});
});
};
this.isJarFilePresent = (elasticMqServerJarName) => {
return (0, fs_1.existsSync)(elasticMqServerJarName);
};
this.spawnElasticMqProcess = async (options) => {
await this.downloadElasticMqIfNecessary();
const port = (options.port || 9324).toString();
const args = [];
const confFile = `
include classpath("application.conf")
// What is the outside visible address of this ElasticMQ node
// Used to create the queue URL (may be different from bind address!)
node-address {
protocol = http
host = localhost
port = ${port}
context-path = ""
}
rest-sqs {
enabled = true
bind-port = ${port}
bind-hostname = "0.0.0.0"
// Possible values: relaxed, strict
sqs-limits = strict
}
// Should the node-address be generated from the bind port/hostname
// Set this to true e.g. when assigning port automatically by using port 0.
generate-node-address = false
queues {
// See next section
}
// Region and accountId which will be included in resource ids
aws {
region = us-west-2
accountId = 000000000000
}
`;
await fs_1.promises.writeFile(`${MQ_LOCAL_PATH}/custom.conf`, confFile);
const elasticMqVersion = this.elasticMqConfig.version || ElasticMQLatestVersion;
const elasticMqServerJarName = this.getJarFileName(elasticMqVersion);
args.push("-jar", "-Dconfig.file=custom.conf", elasticMqServerJarName);
const proc = (0, child_process_1.spawn)("java", args, {
cwd: MQ_LOCAL_PATH,
env: process.env,
});
const startupLog = [];
const started = await this.waitForStart(proc.stdout, startupLog);
if (proc.pid == null || !started) {
throw new Error("Unable to start the Pact Local process");
}
proc.stdout.on("data", (data) => {
this.serverless.cli.log(`ElasticMq Offline: ${data.toString()}`);
});
proc.on("error", (error) => {
this.serverless.cli.log(`ElasticMq Offline error: ${error.toString()}`);
throw error;
});
this.mqInstances[port] = proc;
[
"beforeExit",
"exit",
"SIGINT",
"SIGTERM",
"SIGUSR1",
"SIGUSR2",
"uncaughtException",
].forEach((eventType) => {
process.on(eventType, () => {
this.killElasticMqProcess(this.elasticMqConfig.start);
});
});
return { proc, port, startupLog };
};
this.waitForStart = async (readable, startupLog) => {
let started = false;
for await (const line of (0, stringio_1.chunksToLinesAsync)(readable)) {
startupLog.push(line);
this.serverless.cli.log(line);
if (line.includes(`ElasticMQ server (${this.elasticMqConfig.version}) started`)) {
return (started = true);
}
}
return started;
};
this.killElasticMqProcess = (options) => {
const port = (options.port || 9324).toString();
if (this.mqInstances[port] != null) {
this.mqInstances[port].kill("SIGKILL");
delete this.mqInstances[port];
}
};
this.shouldExecute = () => {
if (this.elasticMqConfig.stages &&
this.elasticMqConfig.stages.includes(this.serverless.service.provider.stage)) {
return true;
}
return false;
};
this.startElasticMq = async () => {
if (this.elasticMqConfig.start.noStart || !this.shouldExecute()) {
this.serverless.cli.log("ElasticMq Offline - [noStart] options is true. Will not start.");
return;
}
const { port, proc } = await this.spawnElasticMqProcess(this.elasticMqConfig.start);
this.serverless.cli.log(`ElasticMq Offline - Started, curl http://0.0.0.0:${port} -d {}`);
await Promise.resolve(proc.pid);
};
this.stopElasticMq = async () => {
this.killElasticMqProcess(this.elasticMqConfig.start);
this.serverless.cli.log("ElasticMq Process - Stopped");
};
this.commands = {};
this.elasticMqConfig = ((_b = (_a = this.serverless.service) === null || _a === void 0 ? void 0 : _a.custom) === null || _b === void 0 ? void 0 : _b.elasticmq) || {};
this.hooks = {
"before:offline:start:end": this.stopElasticMq,
"before:offline:start": this.startElasticMq,
"before:offline:start:init": this.startElasticMq,
};
}
}
module.exports = ServerlessOfflineElasticMqPlugin;
//# sourceMappingURL=index.js.map