mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-06 08:00:44 +00:00
create servers, docker commands
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
readJSONFile,
|
||||
} from "@monitor/util";
|
||||
|
||||
export const CORE_SERVER_NAME = getStringFromEnv("CORE_SERVER_NAME", "Monitor Core");
|
||||
export const SECRETS = readJSONFile("secrets.json");
|
||||
export const LOG = getBooleanFromEnv("LOG", false);
|
||||
export const PORT = getNumberFromEnv("PORT", 8000);
|
||||
@@ -15,3 +16,8 @@ export const MONGO_URL = getStringFromEnv(
|
||||
);
|
||||
export const TOKEN_EXPIRES_IN = getNumberFromEnv("TOKEN_EXPIRES_IN", 3000);
|
||||
export const PASSWORD_SALT_ROUNDS = getNumberFromEnv("PASSWORD_SALT_ROUNDS", 8);
|
||||
export const SYSROOT = getStringFromEnv("SYSROOT", "/home/ubuntu/"); // the root folder monitor has access to, prepends volumes mounted using useSysroot
|
||||
export const ROOT = getStringFromEnv("ROOT", "/rootDir/"); // the root folder in the container that SYSROOT is mounted on
|
||||
export const DEPLOYDATA_ROOT = "deployments/";
|
||||
export const REPO_PATH = ROOT + "builds/";
|
||||
export const REGISTRY_URL = getStringFromEnv("REGISTRY_URL", "localhost:5000/");
|
||||
+3
-1
@@ -4,10 +4,12 @@ import auth from "./util/auth";
|
||||
import { LOG, PORT } from "./config";
|
||||
import db from "./util/db";
|
||||
import ws from "./util/ws";
|
||||
import docker from "./util/docker";
|
||||
|
||||
const app = fastify({ logger: LOG })
|
||||
.register(fastifyCors)
|
||||
.register(fastifyCors)
|
||||
.register(db)
|
||||
.register(docker)
|
||||
.register(auth)
|
||||
.register(ws);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Build } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import { Schema } from "mongoose";
|
||||
|
||||
const builds = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
const schema = new Schema({
|
||||
const schema = new Schema<Build>({
|
||||
name: { type: String, unique: true, index: true },
|
||||
/* repo related */
|
||||
repo: String,
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { Deployment } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import { Schema } from "mongoose";
|
||||
import { Conversion, EnvironmentVar, Volume } from "./misc";
|
||||
|
||||
const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
const schema = new Schema({
|
||||
const schema = new Schema<Deployment>({
|
||||
name: { type: String, unique: true, index: true },
|
||||
containerName: { type: String, unique: true, index: true }, // for auto pull of frontend repo as well
|
||||
owner: { type: String, index: true },
|
||||
serverID: { type: String, index: true },
|
||||
buildID: { type: String, index: true }, // if deploying a monitor build
|
||||
@@ -22,7 +24,6 @@ const deployments = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
/* to manage repo for static frontend, mounted as a volume */
|
||||
repo: String,
|
||||
accessToken: String,
|
||||
pullName: { type: String, index: true }, // for auto pull of repo
|
||||
containerMount: String, // the file path to mount repo on inside the container
|
||||
});
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@ import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import mongoose, { Model } from "mongoose";
|
||||
import { MONGO_URL } from "../../config";
|
||||
import { Build, Deployment, Update, User } from "@monitor/types";
|
||||
import { Build, Deployment, Server, Update, User } from "@monitor/types";
|
||||
import users from "./users";
|
||||
import updates from "./updates";
|
||||
import deployments from "./deployments";
|
||||
import builds from "./builds";
|
||||
import servers from "./servers";
|
||||
|
||||
declare module "fastify" {
|
||||
interface FastifyInstance {
|
||||
@@ -15,6 +16,7 @@ declare module "fastify" {
|
||||
deployments: Model<Deployment>;
|
||||
builds: Model<Build>;
|
||||
updates: Model<Update>;
|
||||
servers: Model<Server>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +27,7 @@ const db = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
|
||||
app
|
||||
.register(users)
|
||||
.register(servers)
|
||||
.register(deployments)
|
||||
.register(builds)
|
||||
.register(updates);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Server } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import { Schema } from "mongoose";
|
||||
|
||||
const servers = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
const schema = new Schema<Server>({
|
||||
name: { type: String, unique: true },
|
||||
address: String,
|
||||
password: String,
|
||||
port: String,
|
||||
rootDirectory: String,
|
||||
enabled: Boolean,
|
||||
useHTTP: Boolean,
|
||||
});
|
||||
|
||||
app.decorate("servers", app.mongoose.model("Server", schema));
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
export default servers;
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Update } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import { Schema } from "mongoose";
|
||||
import { Log } from "./misc";
|
||||
|
||||
const updates = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
const schema = new Schema({
|
||||
const schema = new Schema<Update>({
|
||||
buildID: { type: String, index: true },
|
||||
deploymentID: { type: String, index: true },
|
||||
serverID: { type: String, index: true },
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { User } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
import { Schema } from "mongoose";
|
||||
|
||||
const users = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
const schema = new Schema({
|
||||
const schema = new Schema<User>({
|
||||
username: { type: String, index: true, required: true },
|
||||
permissions: { type: Number, default: 0 },
|
||||
password: String,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Build } from "@monitor/types";
|
||||
import { REGISTRY_URL, REPO_PATH } from "../../config";
|
||||
import { toDashedName } from "../helpers";
|
||||
|
||||
export function createDockerBuild({
|
||||
name,
|
||||
buildPath,
|
||||
dockerfilePath,
|
||||
pullName,
|
||||
}: Build) {
|
||||
return `cd ${REPO_PATH}${pullName}${
|
||||
buildPath ? (buildPath[0] === "/" ? buildPath : "/" + buildPath) : ""
|
||||
} && docker build -t ${
|
||||
REGISTRY_URL + toDashedName(name)
|
||||
} -f ${dockerfilePath} . && docker push ${
|
||||
REGISTRY_URL + toDashedName(name)
|
||||
}`;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ContainerStatus, Deployment } from "@monitor/types";
|
||||
import { objFrom2Arrays } from "@monitor/util";
|
||||
import { FastifyInstance } from "fastify";
|
||||
|
||||
export async function allContainerStatusLocal(
|
||||
app: FastifyInstance,
|
||||
deploymentsAr: Deployment[]
|
||||
) {
|
||||
const statusAr = await app.dockerode.listContainers({ all: true });
|
||||
const statusNames = statusAr.map((stat) =>
|
||||
stat.Names[0].slice(1, stat.Names[0].length)
|
||||
); // they all start with '/'
|
||||
const status = objFrom2Arrays(
|
||||
statusNames,
|
||||
statusAr.map((stat, i) => ({
|
||||
name: statusNames[i],
|
||||
Status: stat.Status,
|
||||
State: stat.State as "running" | "exited",
|
||||
}))
|
||||
);
|
||||
return objFrom2Arrays(
|
||||
statusNames,
|
||||
statusNames.map((name) => {
|
||||
const tryDeployment = getDeployment(status[name], deploymentsAr);
|
||||
const _id = tryDeployment ? tryDeployment._id : "none";
|
||||
return {
|
||||
...status[name],
|
||||
deploymentID: _id,
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function getDeployment(
|
||||
status: ContainerStatus,
|
||||
deploymentsAr: Deployment[]
|
||||
) {
|
||||
for (let i = 0; i < deploymentsAr.length; i++) {
|
||||
if (deploymentsAr[i].containerName === status.name) {
|
||||
return deploymentsAr[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import Dockerode from "dockerode";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
|
||||
declare module "fastify" {
|
||||
interface FastifyInstance {
|
||||
dockerode: Dockerode;
|
||||
}
|
||||
}
|
||||
|
||||
const docker = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
app.decorate("dockerode", new Dockerode());
|
||||
done();
|
||||
});
|
||||
|
||||
export default docker;
|
||||
@@ -0,0 +1,87 @@
|
||||
import { Build, Conversion, Deployment, EnvironmentVar, Volume } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import { DEPLOYDATA_ROOT, REGISTRY_URL, SYSROOT } from "../../config";
|
||||
|
||||
export async function createDockerRun(
|
||||
app: FastifyInstance,
|
||||
{
|
||||
buildID,
|
||||
image,
|
||||
latest,
|
||||
ports,
|
||||
environment,
|
||||
network,
|
||||
volumes,
|
||||
restart,
|
||||
postImage,
|
||||
containerName,
|
||||
containerUser,
|
||||
}: Deployment,
|
||||
) {
|
||||
const _image = buildID
|
||||
? REGISTRY_URL +
|
||||
((await app.builds.findById(buildID)) as any as Build).imageName
|
||||
: image;
|
||||
return (
|
||||
`docker pull ${_image}${buildID || latest ? ":latest" : ""} && ` +
|
||||
`docker run -d --name ${containerName}` +
|
||||
containerUserString(containerUser) +
|
||||
portsString(ports) +
|
||||
volsString(containerName!, volumes) +
|
||||
envString(environment) +
|
||||
restartString(restart) +
|
||||
networkString(network) +
|
||||
` ${_image}${buildID || latest ? ":latest" : ""}${
|
||||
postImage ? " " + postImage : ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
function portsString(ports?: Conversion[]) {
|
||||
return ports && ports.length > 0
|
||||
? ports
|
||||
.map(({ local, container }) => ` -p ${local}:${container}`)
|
||||
.reduce((prev, curr) => prev + curr)
|
||||
: "";
|
||||
}
|
||||
|
||||
function volsString(folderName: string, volumes?: Volume[]) {
|
||||
return volumes && volumes.length > 0
|
||||
? volumes
|
||||
.map(({ local, container, useSystemRoot }) => {
|
||||
const mid = useSystemRoot ? "" : `${DEPLOYDATA_ROOT}${folderName}/`;
|
||||
const localString =
|
||||
local.length > 0
|
||||
? local[0] === "/"
|
||||
? local.slice(1, local.length)
|
||||
: local
|
||||
: "";
|
||||
return ` -v ${SYSROOT + mid + localString}:${container}`;
|
||||
})
|
||||
.reduce((prev, curr) => prev + curr)
|
||||
: "";
|
||||
}
|
||||
|
||||
function restartString(restart?: string) {
|
||||
return restart
|
||||
? ` --restart=${restart}${restart === "on-failure" ? ":10" : ""}`
|
||||
: "";
|
||||
}
|
||||
|
||||
function envString(environment?: EnvironmentVar[]) {
|
||||
return environment && environment.length > 0
|
||||
? environment
|
||||
.map(({ variable, value }) => ` -e "${variable}=${value}"`)
|
||||
.reduce((prev, curr) => prev + curr)
|
||||
: "";
|
||||
}
|
||||
|
||||
function networkString(network?: string) {
|
||||
return network ? ` --network=${network}` : "";
|
||||
}
|
||||
|
||||
function containerUserString(containerUser?: string) {
|
||||
return containerUser && containerUser.length > 0
|
||||
? ` -u ${containerUser}`
|
||||
: "";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Deployment, Server } from "@monitor/types";
|
||||
import { FastifyInstance } from "fastify";
|
||||
|
||||
export function toDashedName(name: string) {
|
||||
return name.toLowerCase().replaceAll(" ", "-");
|
||||
}
|
||||
|
||||
export async function getDeploymentAndServer(
|
||||
app: FastifyInstance,
|
||||
deploymentID: string
|
||||
) {
|
||||
const deployment = (await app.deployments.findById(
|
||||
deploymentID
|
||||
)) as Deployment;
|
||||
return {
|
||||
deployment,
|
||||
server: (await app.servers.findById(deployment.serverID)) as Server,
|
||||
};
|
||||
}
|
||||
+2
-1
@@ -6,7 +6,8 @@
|
||||
"es2019",
|
||||
"es2020.promise",
|
||||
"es2020.bigint",
|
||||
"es2020.string"
|
||||
"es2020.string",
|
||||
"ESNext"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"target": "es2019",
|
||||
|
||||
Vendored
+1
-1
@@ -86,7 +86,7 @@ export type Deployment = {
|
||||
/* to manage repo for static frontend, mounted as a volume */
|
||||
repo?: string;
|
||||
accessToken?: string;
|
||||
pullName?: string; // for auto pull of repo
|
||||
containerName?: string; // also for auto pull of frontend repo
|
||||
containerMount?: string; // the file path to mount repo on inside the container
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Collection } from "@monitor/types";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
export function readJSONFile<T = any>(path: string): T {
|
||||
@@ -19,3 +20,11 @@ export function getBooleanFromEnv(varName: string, defaultValue: boolean) {
|
||||
else if (variable === "false") return false;
|
||||
else return defaultValue;
|
||||
}
|
||||
|
||||
export function objFrom2Arrays<T>(keys: string[], entries: T[]): Collection<T> {
|
||||
return Object.fromEntries(
|
||||
keys.map((id, index) => {
|
||||
return [id, entries[index]];
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user