[FEATURE] Massively increased loading time
This commit is contained in:
parent
b989f6efbe
commit
1a79ea7960
13 changed files with 145 additions and 55 deletions
|
@ -2,3 +2,6 @@
|
||||||
Minecluster or MCL is a web interface used to manage multiple instance of Minecraft Servers in Kubernetes. This app is built to be an all in one for self-hosting Minecraft server. It uses rendered helm charts based on itzg/minecraft-server
|
Minecluster or MCL is a web interface used to manage multiple instance of Minecraft Servers in Kubernetes. This app is built to be an all in one for self-hosting Minecraft server. It uses rendered helm charts based on itzg/minecraft-server
|
||||||
|
|
||||||
More info coming soon.
|
More info coming soon.
|
||||||
|
|
||||||
|
## ⚠ Warning ⚠
|
||||||
|
Development is very active and there is no garuntee for compatability or migration across versions 1/15/24
|
||||||
|
|
|
@ -24,12 +24,13 @@ function payloadFilter(req, res) {
|
||||||
if (!version) return res.status(400).send("Server version is required!");
|
if (!version) return res.status(400).send("Server version is required!");
|
||||||
if (!serverType) return res.status(400).send("Server type is required!");
|
if (!serverType) return res.status(400).send("Server type is required!");
|
||||||
if (!memory) return res.status(400).send("Memory is required!");
|
if (!memory) return res.status(400).send("Memory is required!");
|
||||||
|
// TODO: Impliment non creation time backups
|
||||||
if (
|
if (
|
||||||
!!backupHost ||
|
!!backupHost ||
|
||||||
!!backupBucket ||
|
!!backupBucket ||
|
||||||
!!backupId ||
|
!!backupId ||
|
||||||
!!backupKey ||
|
!!backupKey ||
|
||||||
!backupInterval
|
!!backupInterval
|
||||||
) {
|
) {
|
||||||
// If any keys are required, all are required
|
// If any keys are required, all are required
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -7,6 +7,7 @@ CREATE TABLE servers (
|
||||||
server_type varchar(63) DEFAULT 'VANILLA',
|
server_type varchar(63) DEFAULT 'VANILLA',
|
||||||
cpu varchar(63) DEFAULT '500',
|
cpu varchar(63) DEFAULT '500',
|
||||||
memory varchar(63) DEFAULT '512',
|
memory varchar(63) DEFAULT '512',
|
||||||
|
backup_enabled BOOLEAN DEFAULT FALSE,
|
||||||
backup_host varchar(255) DEFAULT NULL,
|
backup_host varchar(255) DEFAULT NULL,
|
||||||
backup_bucket_path varchar(255) DEFAULT NULL,
|
backup_bucket_path varchar(255) DEFAULT NULL,
|
||||||
backup_id varchar(255) DEFAULT NULL,
|
backup_id varchar(255) DEFAULT NULL,
|
||||||
|
|
|
@ -28,6 +28,7 @@ export async function createServerEntry(serverSpec) {
|
||||||
version,
|
version,
|
||||||
server_type,
|
server_type,
|
||||||
memory,
|
memory,
|
||||||
|
backup_enabled: !!backup_interval, // We already verified the payload, so any backup key will work
|
||||||
backup_host,
|
backup_host,
|
||||||
backup_bucket_path,
|
backup_bucket_path,
|
||||||
backup_id,
|
backup_id,
|
||||||
|
@ -44,9 +45,29 @@ export async function createServerEntry(serverSpec) {
|
||||||
version,
|
version,
|
||||||
server_type: serverType,
|
server_type: serverType,
|
||||||
memory,
|
memory,
|
||||||
|
backup_enabled: backupEnabled,
|
||||||
|
backup_host: backupHost,
|
||||||
|
backup_bucket_path: backupPath,
|
||||||
|
backup_id: backupId,
|
||||||
|
backup_key: backupKey,
|
||||||
|
backup_interval: backupInterval,
|
||||||
} = entries[0];
|
} = entries[0];
|
||||||
const mclName = getMclName(host, id);
|
const mclName = getMclName(host, id);
|
||||||
return { name, mclName, id, host, version, serverType, memory };
|
return {
|
||||||
|
name,
|
||||||
|
mclName,
|
||||||
|
id,
|
||||||
|
host,
|
||||||
|
version,
|
||||||
|
serverType,
|
||||||
|
memory,
|
||||||
|
backupEnabled,
|
||||||
|
backupHost,
|
||||||
|
backupPath,
|
||||||
|
backupId,
|
||||||
|
backupKey,
|
||||||
|
backupInterval,
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
asExpressClientError(e);
|
asExpressClientError(e);
|
||||||
}
|
}
|
||||||
|
@ -73,6 +94,7 @@ export async function getServerEntry(serverId) {
|
||||||
version,
|
version,
|
||||||
server_type: serverType,
|
server_type: serverType,
|
||||||
memory,
|
memory,
|
||||||
|
backup_enabled: backupEnabled,
|
||||||
backup_host: backupHost,
|
backup_host: backupHost,
|
||||||
backup_bucket_path: backupPath,
|
backup_bucket_path: backupPath,
|
||||||
backup_id: backupId,
|
backup_id: backupId,
|
||||||
|
@ -88,12 +110,12 @@ export async function getServerEntry(serverId) {
|
||||||
version,
|
version,
|
||||||
serverType,
|
serverType,
|
||||||
memory,
|
memory,
|
||||||
|
backupEnabled,
|
||||||
backupHost,
|
backupHost,
|
||||||
backupPath,
|
backupPath,
|
||||||
backupId,
|
backupId,
|
||||||
backupKey,
|
backupKey,
|
||||||
backupInterval
|
backupInterval,
|
||||||
|
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
asExpressClientError(e);
|
asExpressClientError(e);
|
||||||
|
|
|
@ -6,23 +6,21 @@ env:
|
||||||
image: garethflowers/ftp-server
|
image: garethflowers/ftp-server
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
exec:
|
exec: { command: ["echo"] }
|
||||||
command: ["echo"]
|
failureThreshold: 20
|
||||||
failureThreshold: 20
|
initialDelaySeconds: 0
|
||||||
initialDelaySeconds: 5
|
periodSeconds: 5
|
||||||
periodSeconds: 5
|
successThreshold: 1
|
||||||
successThreshold: 1
|
timeoutSeconds: 1
|
||||||
timeoutSeconds: 1
|
|
||||||
name: changeme-name-ftp
|
name: changeme-name-ftp
|
||||||
ports: [] # Programatically add all the ports for easier readability, Ports include: 20,21,40000-400009
|
ports: [] # Programatically add all the ports for easier readability, Ports include: 20,21,40000-400009
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
exec:
|
exec: { command: ["echo"] }
|
||||||
command: ["echo"]
|
failureThreshold: 20
|
||||||
failureThreshold: 20
|
initialDelaySeconds: 0
|
||||||
initialDelaySeconds: 5
|
periodSeconds: 5
|
||||||
periodSeconds: 5
|
successThreshold: 1
|
||||||
successThreshold: 1
|
timeoutSeconds: 1
|
||||||
timeoutSeconds: 1
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 50m
|
cpu: 50m
|
||||||
|
|
|
@ -72,12 +72,10 @@ env:
|
||||||
image: itzg/minecraft-server:latest
|
image: itzg/minecraft-server:latest
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
exec:
|
exec: { command: [mc-health] }
|
||||||
# command: ["mc-health"] # This is super unsafe... but why not :)
|
failureThreshold: 200
|
||||||
command: ["echo"]
|
initialDelaySeconds: 30
|
||||||
failureThreshold: 20
|
periodSeconds: 3
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 5
|
|
||||||
successThreshold: 1
|
successThreshold: 1
|
||||||
timeoutSeconds: 1
|
timeoutSeconds: 1
|
||||||
name: changeme-name-server
|
name: changeme-name-server
|
||||||
|
@ -88,15 +86,13 @@ ports:
|
||||||
- containerPort: 25575
|
- containerPort: 25575
|
||||||
name: rcon
|
name: rcon
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
readinessProbe:
|
# readinessProbe: # Disabling this allows for users to manipulate files even if the container is starting
|
||||||
exec:
|
# exec: {command: [mc-health]}
|
||||||
# command: ["mc-health"] # This is super unsafe... but why not :)
|
# failureThreshold: 200
|
||||||
command: ["echo"]
|
# initialDelaySeconds: 30
|
||||||
failureThreshold: 20
|
# periodSeconds: 3
|
||||||
initialDelaySeconds: 5
|
# successThreshold: 1
|
||||||
periodSeconds: 5
|
# timeoutSeconds: 1
|
||||||
successThreshold: 1
|
|
||||||
timeoutSeconds: 1
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 500m
|
cpu: 500m
|
||||||
|
|
|
@ -35,10 +35,10 @@ spec:
|
||||||
claimName: changeme-pvc-name
|
claimName: changeme-pvc-name
|
||||||
- emptyDir: {}
|
- emptyDir: {}
|
||||||
name: backupdir
|
name: backupdir
|
||||||
- name: rclone-config
|
# - name: rclone-config
|
||||||
secret:
|
# secret:
|
||||||
defaultMode: 420
|
# defaultMode: 420
|
||||||
items:
|
# items:
|
||||||
- key: rclone.conf
|
# - key: rclone.conf
|
||||||
path: rclone.conf
|
# path: rclone.conf
|
||||||
secretName: rclone-config
|
# secretName: rclone-config
|
||||||
|
|
|
@ -66,13 +66,18 @@ export function getServerAssets(serverId) {
|
||||||
|
|
||||||
if (deployments.length > 1) throw Error("Deployment filter broken!");
|
if (deployments.length > 1) throw Error("Deployment filter broken!");
|
||||||
if (volumes.length > 1) throw Error("Volume filter broken!");
|
if (volumes.length > 1) throw Error("Volume filter broken!");
|
||||||
if (secrets.length > 1) throw Error("Secrets broken!");
|
if (secrets.length > 2) throw Error("Secrets broken!");
|
||||||
const serverAssets = {
|
const serverAssets = {
|
||||||
deployment: deployments[0],
|
deployment: deployments[0],
|
||||||
service: services.find((s) => s.metadata.name.endsWith("-server")),
|
service: services.find((s) => s.metadata.name.endsWith("-server")),
|
||||||
volume: volumes[0],
|
volume: volumes[0],
|
||||||
rconService: services.find((s) => s.metadata.name.endsWith("-rcon")),
|
rconService: services.find((s) => s.metadata.name.endsWith("-rcon")),
|
||||||
rconSecret: secrets[0],
|
rconSecret: secrets.find((s) =>
|
||||||
|
s.metadata.name.endsWith("-rcon-secret"),
|
||||||
|
),
|
||||||
|
backupSecret: secrets.find((s) =>
|
||||||
|
s.metadata.name.endsWith("-backup-secret"),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
for (var k in serverAssets) if (serverAssets[k]) return serverAssets;
|
for (var k in serverAssets) if (serverAssets[k]) return serverAssets;
|
||||||
// If no assets exist, return nothing
|
// If no assets exist, return nothing
|
||||||
|
@ -96,26 +101,36 @@ export async function getContainers(serverId) {
|
||||||
return deployment.spec.template.spec.containers;
|
return deployment.spec.template.spec.containers;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function containerControl(serverId, deployment, scaleUp) {
|
async function containerControl(serverSpec, deployment, scaleUp) {
|
||||||
const { containers } = deployment.spec.template.spec;
|
const { containers } = deployment.spec.template.spec;
|
||||||
const depFtp = containers.find((c) => c.name.endsWith("-ftp"));
|
const depFtp = containers.find((c) => c.name.endsWith("-ftp"));
|
||||||
const depServer = containers.find((c) => c.name.endsWith("-server"));
|
const depServer = containers.find((c) => c.name.endsWith("-server"));
|
||||||
const depBackup = containers.find((c) => c.name.endsWith("-backup"));
|
const depBackup = containers.find((c) => c.name.endsWith("-backup"));
|
||||||
const serverSpec = await getServerEntry(serverId);
|
|
||||||
const ftpContainer = depFtp ?? getFtpContainer(serverSpec);
|
const ftpContainer = depFtp ?? getFtpContainer(serverSpec);
|
||||||
const serverContainer = depServer ?? getCoreServerContainer(serverSpec);
|
const serverContainer = depServer ?? getCoreServerContainer(serverSpec);
|
||||||
const backupContainer = depBackup ?? getBackupContainer(serverSpec);
|
const backupContainer = depBackup ?? getBackupContainer(serverSpec);
|
||||||
if (scaleUp) return [ftpContainer, serverContainer];
|
if (scaleUp && serverSpec.backupEnabled)
|
||||||
|
return [ftpContainer, serverContainer, backupContainer];
|
||||||
|
else if (scaleUp) return [ftpContainer, serverContainer];
|
||||||
return [ftpContainer];
|
return [ftpContainer];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function terminationControl(containers) {
|
||||||
|
return containers.length > 1 ? 30 /*seconds*/ : 1 /*seconds */;
|
||||||
|
}
|
||||||
|
|
||||||
export async function toggleServer(serverId, scaleUp = false) {
|
export async function toggleServer(serverId, scaleUp = false) {
|
||||||
const deployment = await getDeployment(serverId);
|
const [deployment, serverSpec] = await Promise.all([
|
||||||
deployment.spec.template.spec.containers = await containerControl(
|
getDeployment(serverId),
|
||||||
serverId,
|
getServerEntry(serverId),
|
||||||
deployment,
|
]);
|
||||||
scaleUp,
|
const containers = await containerControl(serverSpec, deployment, scaleUp);
|
||||||
);
|
const ts = terminationControl(containers);
|
||||||
|
|
||||||
|
// Speed up container termination if not running a server
|
||||||
|
deployment.spec.template.spec.terminationGracePeriodSeconds = ts;
|
||||||
|
deployment.spec.template.spec.containers = containers;
|
||||||
|
|
||||||
return k8sDeps.replaceNamespacedDeployment(
|
return k8sDeps.replaceNamespacedDeployment(
|
||||||
deployment.metadata.name,
|
deployment.metadata.name,
|
||||||
namespace,
|
namespace,
|
||||||
|
|
|
@ -62,6 +62,17 @@ export function getServerContainer(serverSpec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBackupContainer(serverSpec) {
|
export function getBackupContainer(serverSpec) {
|
||||||
|
const { mclName, backupEnabled, backupPath } = serverSpec;
|
||||||
const container = loadYaml("lib/k8s/configs/containers/minecraft-backup.yml");
|
const container = loadYaml("lib/k8s/configs/containers/minecraft-backup.yml");
|
||||||
|
if (!backupEnabled) return;
|
||||||
|
const findEnv = (k) => container.env.find(({ name: n }) => n === k);
|
||||||
|
const updateEnv = (k, v) => (findEnv(k).value = v);
|
||||||
|
updateEnv("RCLONE_REMOTE", `${mclName}-backup`);
|
||||||
|
updateEnv("RCLONE_DEST_DIR", backupPath);
|
||||||
|
container.name = `mcl-${mclName}-backup`;
|
||||||
|
// RCON
|
||||||
|
const rs = `mcl-${mclName}-rcon-secret`;
|
||||||
|
findEnv("RCON_PASSWORD").valueFrom.secretKeyRef.name = rs;
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,28 @@ const namespace = process.env.MCL_SERVER_NAMESPACE;
|
||||||
|
|
||||||
const loadYaml = (f) => yaml.load(fs.readFileSync(path.resolve(f), "utf8"));
|
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) {
|
function createRconSecret(serverSpec) {
|
||||||
const { mclName, id } = serverSpec;
|
const { mclName, id } = serverSpec;
|
||||||
const rconYaml = loadYaml("lib/k8s/configs/rcon-secret.yml");
|
const rconYaml = loadYaml("lib/k8s/configs/rcon-secret.yml");
|
||||||
|
@ -39,12 +61,12 @@ function createServerVolume(serverSpec) {
|
||||||
volumeYaml.metadata.name = `mcl-${mclName}-volume`;
|
volumeYaml.metadata.name = `mcl-${mclName}-volume`;
|
||||||
volumeYaml.metadata.namespace = namespace;
|
volumeYaml.metadata.namespace = namespace;
|
||||||
volumeYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
volumeYaml.metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||||
volumeYaml.spec.resources.requests.storage = "1Gi"; // TODO: Changeme
|
volumeYaml.spec.resources.requests.storage = "5Gi"; // TODO: Changeme
|
||||||
return volumeYaml;
|
return volumeYaml;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createServerDeploy(serverSpec) {
|
function createServerDeploy(serverSpec) {
|
||||||
const { mclName, id } = serverSpec;
|
const { mclName, id, backupEnabled } = serverSpec;
|
||||||
const deployYaml = loadYaml("lib/k8s/configs/server-deployment.yml");
|
const deployYaml = loadYaml("lib/k8s/configs/server-deployment.yml");
|
||||||
const { metadata } = deployYaml;
|
const { metadata } = deployYaml;
|
||||||
const serverContainer = getServerContainer(serverSpec);
|
const serverContainer = getServerContainer(serverSpec);
|
||||||
|
@ -57,6 +79,8 @@ function createServerDeploy(serverSpec) {
|
||||||
metadata.annotations["minecluster.dunemask.net/id"] = id;
|
metadata.annotations["minecluster.dunemask.net/id"] = id;
|
||||||
deployYaml.metadata = metadata;
|
deployYaml.metadata = metadata;
|
||||||
|
|
||||||
|
deployYaml.spec.template.spec.terminationGracePeriodSeconds = 1;
|
||||||
|
|
||||||
// Configure Lables & Selectors
|
// Configure Lables & Selectors
|
||||||
deployYaml.spec.selector.matchLabels.app = `mcl-${mclName}-app`;
|
deployYaml.spec.selector.matchLabels.app = `mcl-${mclName}-app`;
|
||||||
deployYaml.spec.template.metadata.labels.app = `mcl-${mclName}-app`;
|
deployYaml.spec.template.metadata.labels.app = `mcl-${mclName}-app`;
|
||||||
|
@ -68,6 +92,18 @@ function createServerDeploy(serverSpec) {
|
||||||
({ name }) => name === "datadir",
|
({ name }) => name === "datadir",
|
||||||
).persistentVolumeClaim.claimName = `mcl-${mclName}-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
|
// 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.template.spec.containers.push(ftpContainer);
|
||||||
|
@ -119,12 +155,14 @@ function createRconService(createSpec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function createServerResources(createSpec) {
|
export default async function createServerResources(createSpec) {
|
||||||
|
const backupSecret = createBackupSecret(createSpec);
|
||||||
const rconSecret = createRconSecret(createSpec);
|
const rconSecret = createRconSecret(createSpec);
|
||||||
const serverVolume = createServerVolume(createSpec);
|
const serverVolume = createServerVolume(createSpec);
|
||||||
const serverDeploy = createServerDeploy(createSpec);
|
const serverDeploy = createServerDeploy(createSpec);
|
||||||
const serverService = createServerService(createSpec);
|
const serverService = createServerService(createSpec);
|
||||||
const rconService = createRconService(createSpec);
|
const rconService = createRconService(createSpec);
|
||||||
k8sCore.createNamespacedPersistentVolumeClaim(namespace, serverVolume);
|
k8sCore.createNamespacedPersistentVolumeClaim(namespace, serverVolume);
|
||||||
|
if (!!backupSecret) k8sCore.createNamespacedSecret(namespace, backupSecret);
|
||||||
k8sCore.createNamespacedSecret(namespace, rconSecret);
|
k8sCore.createNamespacedSecret(namespace, rconSecret);
|
||||||
k8sCore.createNamespacedService(namespace, serverService);
|
k8sCore.createNamespacedService(namespace, serverService);
|
||||||
k8sCore.createNamespacedService(namespace, rconService);
|
k8sCore.createNamespacedService(namespace, rconService);
|
||||||
|
|
|
@ -47,6 +47,10 @@ export default async function deleteServerResources(serverSpec) {
|
||||||
const deleteRconSecret = deleteOnExist(server.rconSecret, (name) =>
|
const deleteRconSecret = deleteOnExist(server.rconSecret, (name) =>
|
||||||
k8sCore.deleteNamespacedSecret(name, namespace),
|
k8sCore.deleteNamespacedSecret(name, namespace),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const deleteBackupSecret = deleteOnExist(server.backupSecret, (name) =>
|
||||||
|
k8sCore.deleteNamespacedSecret(name, namespace),
|
||||||
|
);
|
||||||
const deleteVolume = deleteOnExist(server.volume, (name) =>
|
const deleteVolume = deleteOnExist(server.volume, (name) =>
|
||||||
k8sCore.deleteNamespacedPersistentVolumeClaim(name, namespace),
|
k8sCore.deleteNamespacedPersistentVolumeClaim(name, namespace),
|
||||||
);
|
);
|
||||||
|
@ -55,6 +59,7 @@ export default async function deleteServerResources(serverSpec) {
|
||||||
deleteService,
|
deleteService,
|
||||||
deleteRconService,
|
deleteRconService,
|
||||||
deleteRconSecret,
|
deleteRconSecret,
|
||||||
|
deleteBackupSecret,
|
||||||
deleteVolume,
|
deleteVolume,
|
||||||
]).catch(deleteError);
|
]).catch(deleteError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ export async function getInstances() {
|
||||||
const { ftpAvailable, serverAvailable, services } = getServerStatus(s);
|
const { ftpAvailable, serverAvailable, services } = getServerStatus(s);
|
||||||
metrics = getServerMetrics(podMetricsRes, serverId, serverAvailable);
|
metrics = getServerMetrics(podMetricsRes, serverId, serverAvailable);
|
||||||
return {
|
return {
|
||||||
name: entry.name,
|
name: !!entry ? entry.name : "Unknown",
|
||||||
id: serverId,
|
id: serverId,
|
||||||
metrics,
|
metrics,
|
||||||
services,
|
services,
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default function CreateCoreOptions() {
|
||||||
async function upsertSpec() {
|
async function upsertSpec() {
|
||||||
if (validateSpec() !== "validated") return;
|
if (validateSpec() !== "validated") return;
|
||||||
createServer(spec)
|
createServer(spec)
|
||||||
.then(() => nav("/"))
|
// .then(() => nav("/"))
|
||||||
.catch(alert);
|
.catch(alert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue