[FEATURE] Migrated to new loading sequence (#6)
Co-authored-by: Dunemask <dunemask@gmail.com> Reviewed-on: https://gitea.dunemask.dev/elysium/minecluster/pulls/6
This commit is contained in:
parent
fb57c03ba7
commit
6eb4ed3e95
53 changed files with 1349 additions and 449 deletions
|
@ -4,7 +4,7 @@ import k8s from "@kubernetes/client-node";
|
|||
import yaml from "js-yaml";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import ExpressClientError from "../util/ExpressClientError.js";
|
||||
|
||||
import {
|
||||
getFtpContainer,
|
||||
getServerContainer,
|
||||
|
@ -19,33 +19,54 @@ const namespace = process.env.MCL_SERVER_NAMESPACE;
|
|||
|
||||
const loadYaml = (f) => yaml.load(fs.readFileSync(path.resolve(f), "utf8"));
|
||||
|
||||
function createBackupSecret(serverSpec) {
|
||||
if (!serverSpec.backupEnabled) return; // If backup not defined, don't create RCLONE secret
|
||||
const { mclName, id, backupId, backupKey, backupHost } = serverSpec;
|
||||
const backupYaml = loadYaml("lib/k8s/configs/backup-secret.yml");
|
||||
backupYaml.metadata.labels.app = `mcl-${mclName}-app`;
|
||||
backupYaml.metadata.name = `mcl-${mclName}-backup-secret`;
|
||||
backupYaml.metadata.namespace = namespace;
|
||||
backupYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
const rcloneConfig = [
|
||||
`[${mclName}-backup]`,
|
||||
"type = s3",
|
||||
"provider = Minio",
|
||||
"env_auth = false",
|
||||
`access_key_id = ${backupId}`,
|
||||
`secret_access_key = ${backupKey}`,
|
||||
`endpoint = ${backupHost}`,
|
||||
`acl = private`,
|
||||
].join("\n");
|
||||
backupYaml.data["rclone.conf"] = Buffer.from(rcloneConfig).toString("base64");
|
||||
return backupYaml;
|
||||
}
|
||||
|
||||
function createRconSecret(serverSpec) {
|
||||
const { name } = serverSpec;
|
||||
const { mclName, id } = serverSpec;
|
||||
const rconYaml = loadYaml("lib/k8s/configs/rcon-secret.yml");
|
||||
// TODO: Dyamic rconPassword
|
||||
const rconPassword = bcrypt.hashSync(uuidv4(), 10);
|
||||
rconYaml.data["rcon-password"] = Buffer.from(rconPassword).toString("base64");
|
||||
rconYaml.metadata.labels.app = `mcl-${name}-app`;
|
||||
rconYaml.metadata.name = `mcl-${name}-rcon-secret`;
|
||||
rconYaml.metadata.labels.app = `mcl-${mclName}-app`;
|
||||
rconYaml.metadata.name = `mcl-${mclName}-rcon-secret`;
|
||||
rconYaml.metadata.namespace = namespace;
|
||||
rconYaml.metadata.annotations["minecluster.dunemask.net/server-name"] = name;
|
||||
rconYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
return rconYaml;
|
||||
}
|
||||
|
||||
function createServerVolume(serverSpec) {
|
||||
const { name } = serverSpec;
|
||||
const { mclName, id } = serverSpec;
|
||||
const volumeYaml = loadYaml("lib/k8s/configs/server-pvc.yml");
|
||||
volumeYaml.metadata.labels.service = `mcl-${name}-server`;
|
||||
volumeYaml.metadata.name = `mcl-${name}-volume`;
|
||||
volumeYaml.metadata.labels.service = `mcl-${mclName}-server`;
|
||||
volumeYaml.metadata.name = `mcl-${mclName}-volume`;
|
||||
volumeYaml.metadata.namespace = namespace;
|
||||
volumeYaml.metadata.annotations["minecluster.dunemask.net/server-name"] =
|
||||
name;
|
||||
volumeYaml.spec.resources.requests.storage = "1Gi"; // TODO: Changeme
|
||||
volumeYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
volumeYaml.spec.resources.requests.storage = "5Gi"; // TODO: Changeme
|
||||
return volumeYaml;
|
||||
}
|
||||
|
||||
function createServerDeploy(serverSpec) {
|
||||
const { name, host } = serverSpec;
|
||||
const { mclName, id, backupEnabled } = serverSpec;
|
||||
const deployYaml = loadYaml("lib/k8s/configs/server-deployment.yml");
|
||||
const { metadata } = deployYaml;
|
||||
const serverContainer = getServerContainer(serverSpec);
|
||||
|
@ -53,39 +74,54 @@ function createServerDeploy(serverSpec) {
|
|||
const ftpContainer = getFtpContainer(serverSpec);
|
||||
|
||||
// Configure Metadata;
|
||||
metadata.name = `mcl-${name}`;
|
||||
metadata.name = `mcl-${mclName}`;
|
||||
metadata.namespace = namespace;
|
||||
metadata.annotations["minecluster.dunemask.net/server-name"] = name;
|
||||
metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
deployYaml.metadata = metadata;
|
||||
|
||||
deployYaml.spec.template.spec.terminationGracePeriodSeconds = 1;
|
||||
|
||||
// Configure Lables & Selectors
|
||||
deployYaml.spec.selector.matchLabels.app = `mcl-${name}-app`;
|
||||
deployYaml.spec.template.metadata.labels.app = `mcl-${name}-app`;
|
||||
deployYaml.spec.selector.matchLabels.app = `mcl-${mclName}-app`;
|
||||
deployYaml.spec.template.metadata.labels.app = `mcl-${mclName}-app`;
|
||||
deployYaml.spec.template.metadata.annotations["minecluster.dunemask.net/id"] =
|
||||
id;
|
||||
|
||||
// Volumes
|
||||
deployYaml.spec.template.spec.volumes.find(
|
||||
({ name }) => name === "datadir",
|
||||
).persistentVolumeClaim.claimName = `mcl-${name}-volume`;
|
||||
).persistentVolumeClaim.claimName = `mcl-${mclName}-volume`;
|
||||
|
||||
// Backups
|
||||
if (backupEnabled) {
|
||||
deployYaml.spec.template.spec.volumes.push({
|
||||
name: "rclone-config",
|
||||
secret: {
|
||||
defaultMode: 420,
|
||||
items: [{ key: "rclone.conf", path: "rclone.conf" }],
|
||||
secretName: `mcl-${mclName}-backup-secret`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Apply Containers TODO: User control for autostart
|
||||
deployYaml.spec.template.spec.containers.push(serverContainer);
|
||||
// deployYaml.spec.template.spec.containers.push(serverContainer);
|
||||
deployYaml.spec.template.spec.containers.push(ftpContainer);
|
||||
deployYaml.spec.replicas = 1;
|
||||
return deployYaml;
|
||||
}
|
||||
|
||||
function createServerService(serverSpec) {
|
||||
const { name, host } = serverSpec;
|
||||
const { mclName, host, id } = serverSpec;
|
||||
const serviceYaml = loadYaml("lib/k8s/configs/server-svc.yml");
|
||||
serviceYaml.metadata.annotations["ingress.qumine.io/hostname"] = host;
|
||||
serviceYaml.metadata.annotations["mc-router.itzg.me/externalServerName"] =
|
||||
host;
|
||||
serviceYaml.metadata.labels.app = `mcl-${name}-app`;
|
||||
serviceYaml.metadata.name = `mcl-${name}-server`;
|
||||
serviceYaml.metadata.labels.app = `mcl-${mclName}-app`;
|
||||
serviceYaml.metadata.name = `mcl-${mclName}-server`;
|
||||
serviceYaml.metadata.namespace = namespace;
|
||||
serviceYaml.metadata.annotations["minecluster.dunemask.net/server-name"] =
|
||||
name;
|
||||
serviceYaml.spec.selector.app = `mcl-${name}-app`;
|
||||
serviceYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
serviceYaml.spec.selector.app = `mcl-${mclName}-app`;
|
||||
// Port List:
|
||||
const serverPortList = [{ p: 25565, n: "minecraft" }];
|
||||
|
||||
|
@ -107,33 +143,26 @@ function createServerService(serverSpec) {
|
|||
return serviceYaml;
|
||||
}
|
||||
|
||||
function createRconService(serverSpec) {
|
||||
const { name } = serverSpec;
|
||||
function createRconService(createSpec) {
|
||||
const { id, mclName } = createSpec;
|
||||
const rconSvcYaml = loadYaml("lib/k8s/configs/rcon-svc.yml");
|
||||
rconSvcYaml.metadata.labels.app = `mcl-${name}-app`;
|
||||
rconSvcYaml.metadata.name = `mcl-${name}-rcon`;
|
||||
rconSvcYaml.metadata.labels.app = `mcl-${mclName}-app`;
|
||||
rconSvcYaml.metadata.name = `mcl-${mclName}-rcon`;
|
||||
rconSvcYaml.metadata.namespace = namespace;
|
||||
rconSvcYaml.metadata.annotations["minecluster.dunemask.net/server-name"] =
|
||||
name;
|
||||
rconSvcYaml.spec.selector.app = `mcl-${name}-app`;
|
||||
rconSvcYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||
rconSvcYaml.spec.selector.app = `mcl-${mclName}-app`;
|
||||
return rconSvcYaml;
|
||||
}
|
||||
|
||||
export default async function createServerResources(serverSpec) {
|
||||
const deploymentRes = await k8sDeps.listNamespacedDeployment(namespace);
|
||||
const deployments = deploymentRes.body.items.map((i) => i.metadata.name);
|
||||
if (deployments.includes(`mcl-${serverSpec.name}`))
|
||||
throw new ExpressClientError({ m: "Server already exists!", c: 409 });
|
||||
const pvcRes = await k8sCore.listNamespacedPersistentVolumeClaim(namespace);
|
||||
const pvcs = pvcRes.body.items.map((i) => i.metadata.name);
|
||||
if (pvcs.includes(`mcl-${serverSpec.name}-volume`))
|
||||
throw new ExpressClientError({ m: "Server PVC already exists!", c: 409 });
|
||||
const rconSecret = createRconSecret(serverSpec);
|
||||
const serverVolume = createServerVolume(serverSpec);
|
||||
const serverDeploy = createServerDeploy(serverSpec);
|
||||
const serverService = createServerService(serverSpec);
|
||||
const rconService = createRconService(serverSpec);
|
||||
export default async function createServerResources(createSpec) {
|
||||
const backupSecret = createBackupSecret(createSpec);
|
||||
const rconSecret = createRconSecret(createSpec);
|
||||
const serverVolume = createServerVolume(createSpec);
|
||||
const serverDeploy = createServerDeploy(createSpec);
|
||||
const serverService = createServerService(createSpec);
|
||||
const rconService = createRconService(createSpec);
|
||||
k8sCore.createNamespacedPersistentVolumeClaim(namespace, serverVolume);
|
||||
if (!!backupSecret) k8sCore.createNamespacedSecret(namespace, backupSecret);
|
||||
k8sCore.createNamespacedSecret(namespace, rconSecret);
|
||||
k8sCore.createNamespacedService(namespace, serverService);
|
||||
k8sCore.createNamespacedService(namespace, rconService);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue