fivem-docker-cli
Version:
Command-line tool to create and administer FiveM Servers running in Docker.
171 lines (155 loc) • 5.32 kB
JavaScript
const { Command, flags } = require('@oclif/command');
const inquirer = require('inquirer');
const Docker = require('dockerode');
const { getPorts } = require('../modules/getPorts');
// Initialization
const docker = new Docker({ socketPath: "/var/run/docker.sock" });
class InitCommand extends Command {
async run() {
const {flags} = this.parse(InitCommand);
let servername = flags.servername;
let licensekey = flags.licensekey;
let rconpass = flags.rconpass;
const startingPort = 30120;
const endingPort = 30139;
const currentNames = [];
const currentPorts = [];
let isImage = false;
let availablePort;
if (!flags.servername) {
let responses = await inquirer.prompt([{
name: 'servername',
message: 'Enter a name for your server. \n>',
type: 'input'
}]);
servername = responses.servername;
}
if (!flags.licensekey) {
let responses = await inquirer.prompt([{
name: 'licensekey',
message: 'Enter your server license key. This can be obtained from https://keymaster.fivem.net. \n>',
type: 'input'
}]);
licensekey = responses.licensekey;
}
if (!flags.rconpass) {
let responses = await inquirer.prompt([{
name: 'rconpass',
message: 'Enter the password you would like to use for RCON access. \n>',
type: 'input'
}]);
rconpass = responses.rconpass;
}
docker.pull('spritsail/fivem:latest', (err, stream) => {
console.log(stream);
if (err) {
console.error(err);
} else {
isImage = true;
}
});
// Check existing containers
function checkExistingContainers() {
return new Promise((resolve,reject) => {
let error;
docker.listContainers({
all: true,
}).then((containers) => {
containers.forEach((container) => {
// Get names for existing containers
currentNames.push(container.Names[0]);
// Get ports for existing containers
getPorts(container)
.then((ports) => {
ports.forEach((port) => {
if (!currentPorts.includes(parseInt(port.External))){
currentPorts.push(parseInt(port.External, 10));
}
});
})
.catch((err) => error = err);
});
})
.catch((err) => error = err);
if (!error) {
resolve('checkExistingContainers');
} else {
reject(error);
}
})
.catch((err) => console.error(err));
}
// Check server name to see if it already exists
//TODO: Add validation to servername. Must match /?[a-zA-Z0-9_-]+
function checkServerName(servername) {
currentNames.forEach((name) => {
if (name === (servername)) {
return false;
} else {
return true;
}
});
}
// Check designated port range against existing containers for an available port
function getAvailablePort(currentPorts) {
return new Promise((resolve, reject) => {
let err;
for (let i = startingPort; i <= endingPort; i++) {
if (!currentPorts.includes(i) && !availablePort) {
availablePort = i.toString();
break;
} else if(i === endingPort && !availablePort) {
err = 'There are no available ports.';
} else {
err = 'There was an error while checking available ports.';
}
}
if (!err) {
resolve(availablePort);
} else {
reject(err);
}
})
.catch((err) => console.error(err));
}
// Check to make sure all information is available
Promise.all([servername, licensekey, checkExistingContainers(), getAvailablePort(currentPorts)], isImage)
.then((values) => {
createContainer();
});
// Creates new FiveM server in Docker container
function createContainer () {
docker.createContainer({
name: servername,
Image: 'spritsail/fivem:latest',
RestartPolicy: {
name: 'unless-stopped'
},
Binds: [
"/volumes/fivem/" + servername + ":/config"
],
Env: ["LICENCE_KEY=" + licensekey, "RCON_PASSWORD=" + rconpass, ],
PortBindings: {
"30120/tcp": [{ "HostIp": "", "HostPort": availablePort }],
"30120/udp": [{ "HostIp": "", "HostPort": availablePort }]
}
}).then(container => {
console.log('FiveM Container Started:');
console.table({
ID: container.id.slice(0, 11),
Name: servername,
Port: availablePort,
Directory: '/volume/fivem/' + servername
});
return container.start();
}).catch((err) => console.error(err));
}
}
}
InitCommand.description = `Creates a new FiveM server running in Docker.`;
InitCommand.flags = {
servername: flags.string({char: 's', description: 'Name of the FiveM Docker container.'}),
licensekey: flags.string({char: 'k', description: 'Server license key - This can be obtained from https://keymaster.fivem.net.'}),
rconpass: flags.string({char: 'p', description: 'Password for RCON access.'})
};
module.exports = InitCommand;