[FEATURE} Adjust error handling and bump versions

This commit is contained in:
Dunemask 2023-12-08 14:19:02 -07:00
parent d47a8c3cc4
commit 360dd32860
19 changed files with 1052 additions and 455 deletions

View file

@ -18,7 +18,7 @@ export default async function liveLogging(socket, serverNamespace) {
const log = new k8s.Log(kc);
const logStream = new stream.PassThrough();
logStream.on("data", (chunk) =>
socket.emit("push", Buffer.from(chunk).toString())
socket.emit("push", Buffer.from(chunk).toString()),
);
log
.log(serverNamespace, mcsPods[0], containerName, logStream, {

View file

@ -8,21 +8,35 @@ const k8sCore = kc.makeApiClient(k8s.CoreV1Api);
const k8sMetrics = new k8s.Metrics(kc);
const namespace = process.env.MCL_SERVER_NAMESPACE;
async function findDeployment(serverName) {
try {
const deploymentRes = await k8sDeps.listNamespacedDeployment(namespace);
return deploymentRes.body.items.find(
(i) => i.metadata.name === `mcl-${serverName}`,
);
} catch (e) {
ERR("SERVER CONTROL", `Error finding deployment: mcl-${serverName}`);
}
}
export async function startServer(req, res) {
const serverSpec = req.body;
if (!serverSpec) return res.sendStatus(400);
if (!serverSpec.name) return res.status(400).send("Server name required!");
const { name } = serverSpec;
const deploymentRes = await k8sDeps.listNamespacedDeployment(namespace);
const dep = deploymentRes.body.items.find(
(i) => i.metadata.name === `mcl-${name}`
);
if (!dep) return res.status(409).send("Server does not exist!");
const dep = await findDeployment(name);
if (!dep || !dep.spec) return res.status(409).send("Server does not exist!");
if (dep.spec.replicas === 1)
return res.status(409).send("Server already started!");
dep.spec.replicas = 1;
k8sDeps.replaceNamespacedDeployment(`mcl-${name}`, namespace, dep);
res.sendStatus(200);
k8sDeps
.replaceNamespacedDeployment(`mcl-${name}`, namespace, dep)
.then(() => res.sendStatus(200))
.catch((e) => {
ERR("SERVER CONTROL", e);
res.status(500).send("Error updating server!");
});
}
export async function stopServer(req, res) {
@ -32,7 +46,7 @@ export async function stopServer(req, res) {
const { name } = serverSpec;
const deploymentRes = await k8sDeps.listNamespacedDeployment(namespace);
const dep = deploymentRes.body.items.find(
(i) => i.metadata.name === `mcl-${name}`
(i) => i.metadata.name === `mcl-${name}`,
);
if (!dep) return res.status(409).send("Server does not exist!");
if (dep.spec.replicas === 0)
@ -56,7 +70,7 @@ export async function getServers(req, res) {
const podMetricsResponse = await k8sMetrics.getPodMetrics(namespace);
// TODO Add an annotation and manage using that
const serverDeployments = deployments.filter((d) =>
d.metadata.name.startsWith("mcl-")
d.metadata.name.startsWith("mcl-"),
);
var name, metrics, started;
const servers = serverDeployments.map((s) => {
@ -68,10 +82,10 @@ export async function getServers(req, res) {
});
if (pod) {
const podCpus = pod.containers.map(
({ usage }) => parseInt(usage.cpu) / 1_000_000
({ usage }) => parseInt(usage.cpu) / 1_000_000,
);
const podMems = pod.containers.map(
({ usage }) => parseInt(usage.memory) / 1024
({ usage }) => parseInt(usage.memory) / 1024,
);
metrics = {
cpu: Math.ceil(podCpus.reduce((a, b) => a + b)),

View file

@ -30,7 +30,7 @@ function payloadFilter(req, res) {
function createRconSecret(serverSpec) {
const { name } = serverSpec;
const rconYaml = yaml.load(
fs.readFileSync(path.resolve("lib/k8s/configs/rcon-secret.yml"), "utf8")
fs.readFileSync(path.resolve("lib/k8s/configs/rcon-secret.yml"), "utf8"),
);
// TODO: Dyamic rconPassword
@ -45,7 +45,7 @@ function createRconSecret(serverSpec) {
function createServerVolume(serverSpec) {
const { name } = serverSpec;
const volumeYaml = yaml.load(
fs.readFileSync(path.resolve("lib/k8s/configs/server-pvc.yml"), "utf8")
fs.readFileSync(path.resolve("lib/k8s/configs/server-pvc.yml"), "utf8"),
);
volumeYaml.metadata.labels.service = `mcl-${name}-server`;
volumeYaml.metadata.name = `mcl-${name}-volume`;
@ -72,8 +72,8 @@ function createServerDeploy(serverSpec) {
const deployYaml = yaml.load(
fs.readFileSync(
path.resolve("lib/k8s/configs/server-deployment.yml"),
"utf8"
)
"utf8",
),
);
deployYaml.metadata.name = `mcl-${name}`;
deployYaml.metadata.namespace = namespace;
@ -83,30 +83,25 @@ function createServerDeploy(serverSpec) {
deployYaml.spec.template.spec.containers.splice(0, 1); //TODO: Currently removing backup container
const serverContainer = deployYaml.spec.template.spec.containers[0];
const findEnv = (k) => serverContainer.env.find(({ name: n }) => n === k);
const updateEnv = (k, v) => (findEnv.value = v);
// Enviornment variables
serverContainer.env.find(({ name: n }) => n === "TYPE").value = serverType;
serverContainer.env.find(({ name: n }) => n === "VERSION").value = version;
serverContainer.env.find(({ name: n }) => n === "DIFFICULTY").value =
difficulty;
serverContainer.env.find(({ name: n }) => n === "MODE").value = gamemode;
serverContainer.env.find(({ name: n }) => n === "MOTD").value = motd;
serverContainer.env.find(({ name: n }) => n === "MAX_PLAYERS").value =
maxPlayers;
serverContainer.env.find(({ name: n }) => n === "SEED").value = seed;
serverContainer.env.find(({ name: n }) => n === "OPS").value = ops;
serverContainer.env.find(({ name: n }) => n === "WHITELIST").value =
whitelist;
serverContainer.env.find(
({ name: n }) => n === "MEMORY"
).value = `${memory}M`;
if (version !== "VANILLA")
delete serverContainer.env.find(({ name: n }) => n === "MODPACK").value;
else
serverContainer.env.find(({ name: n }) => n === "MODPACK").value = modpack;
updateEnv("TYPE", serverType);
updateEnv("VERSION", version);
updateEnv("DIFFICULTY", difficulty);
updateEnv("MODE", gamemode);
updateEnv("MOTD", motd);
updateEnv("MAX_PLAYERS", maxPlayers);
updateEnv("SEED", seed);
updateEnv("OPS", ops);
updateEnv("WHITELIST", whitelist);
updateEnv("MEMORY", `${memory}M`);
if (version !== "VANILLA") delete findEnv("MODPACK").value;
else updateEnv("MODPACK", modpack);
findEnv("RCON_PASSWORD").valueFrom.secretKeyRef.name =
`mcl-${name}-rcon-secret`;
serverContainer.env.find(
({ name }) => name === "RCON_PASSWORD"
).valueFrom.secretKeyRef.name = `mcl-${name}-rcon-secret`;
// Server Container Name
serverContainer.name = `mcl-${name}`;
// Resources
@ -114,7 +109,7 @@ function createServerDeploy(serverSpec) {
// serverContainer.resources.limits.memory = `${memory}Mi`; // TODO Allow for limits beyond initial startup
// Volumes
deployYaml.spec.template.spec.volumes.find(
({ name }) => name === "datadir"
({ name }) => name === "datadir",
).persistentVolumeClaim.claimName = `mcl-${name}-volume`;
deployYaml.spec.template.spec.containers[0] = serverContainer;
return deployYaml;
@ -123,7 +118,7 @@ function createServerDeploy(serverSpec) {
function createServerService(serverSpec) {
const { name, url } = serverSpec;
const serviceYaml = yaml.load(
fs.readFileSync(path.resolve("lib/k8s/configs/server-svc.yml"), "utf8")
fs.readFileSync(path.resolve("lib/k8s/configs/server-svc.yml"), "utf8"),
);
serviceYaml.metadata.annotations["ingress.qumine.io/hostname"] = url;
serviceYaml.metadata.labels.app = `mcl-${name}-app`;
@ -136,7 +131,7 @@ function createServerService(serverSpec) {
function createRconService(serverSpec) {
const { name, url } = serverSpec;
const rconSvcYaml = yaml.load(
fs.readFileSync(path.resolve("lib/k8s/configs/rcon-svc.yml"), "utf8")
fs.readFileSync(path.resolve("lib/k8s/configs/rcon-svc.yml"), "utf8"),
);
rconSvcYaml.metadata.labels.app = `mcl-${name}-app`;
rconSvcYaml.metadata.name = `mcl-${name}-rcon`;

View file

@ -25,24 +25,24 @@ export default async function deleteServer(req, res) {
// Delete in reverse order
const deleteDeploy = k8sDeps.deleteNamespacedDeployment(
`mcl-${serverSpec.name}`,
namespace
namespace,
);
const deleteService = k8sCore.deleteNamespacedService(
`mcl-${name}-server`,
namespace
namespace,
);
const deleteRconService = k8sCore.deleteNamespacedService(
`mcl-${name}-rcon`,
namespace
namespace,
);
await deleteDeploy.catch(deleteError(res));
const deleteRconSecret = k8sCore.deleteNamespacedSecret(
`mcl-${name}-rcon-secret`,
namespace
namespace,
);
const deleteVolume = k8sCore.deleteNamespacedPersistentVolumeClaim(
`mcl-${name}-volume`,
namespace
namespace,
);
Promise.all([
deleteService,