mirror of
https://github.com/ershisan99/coolify.git
synced 2026-01-26 05:02:13 +00:00
fix: cleanupStuckedContainers
This commit is contained in:
371
apps/trpc-experimental/server/build/trpc/routers/services/lib.js
Normal file
371
apps/trpc-experimental/server/build/trpc/routers/services/lib.js
Normal file
@@ -0,0 +1,371 @@
|
||||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var lib_exports = {};
|
||||
__export(lib_exports, {
|
||||
generatePassword: () => generatePassword,
|
||||
getFreePublicPort: () => getFreePublicPort,
|
||||
parseAndFindServiceTemplates: () => parseAndFindServiceTemplates,
|
||||
persistentVolumes: () => persistentVolumes,
|
||||
startServiceContainers: () => startServiceContainers,
|
||||
verifyAndDecryptServiceSecrets: () => verifyAndDecryptServiceSecrets
|
||||
});
|
||||
module.exports = __toCommonJS(lib_exports);
|
||||
var import_common = require("../../../lib/common");
|
||||
var import_bcryptjs = __toESM(require("bcryptjs"));
|
||||
var import_prisma = require("../../../prisma");
|
||||
var import_crypto = __toESM(require("crypto"));
|
||||
var import_executeCommand = require("../../../lib/executeCommand");
|
||||
async function parseAndFindServiceTemplates(service, workdir, isDeploy = false) {
|
||||
const templates = await (0, import_common.getTemplates)();
|
||||
const foundTemplate = templates.find((t) => (0, import_common.fixType)(t.type) === service.type);
|
||||
let parsedTemplate = {};
|
||||
if (foundTemplate) {
|
||||
if (!isDeploy) {
|
||||
for (const [key, value] of Object.entries(foundTemplate.services)) {
|
||||
const realKey = key.replace("$$id", service.id);
|
||||
let name = value.name;
|
||||
if (!name) {
|
||||
if (Object.keys(foundTemplate.services).length === 1) {
|
||||
name = foundTemplate.name || service.name.toLowerCase();
|
||||
} else {
|
||||
if (key === "$$id") {
|
||||
name = foundTemplate.name || key.replaceAll("$$id-", "") || service.name.toLowerCase();
|
||||
} else {
|
||||
name = key.replaceAll("$$id-", "") || service.name.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
parsedTemplate[realKey] = {
|
||||
value,
|
||||
name,
|
||||
documentation: value.documentation || foundTemplate.documentation || "https://docs.coollabs.io",
|
||||
image: value.image,
|
||||
files: value?.files,
|
||||
environment: [],
|
||||
fqdns: [],
|
||||
hostPorts: [],
|
||||
proxy: {}
|
||||
};
|
||||
if (value.environment?.length > 0) {
|
||||
for (const env of value.environment) {
|
||||
let [envKey, ...envValue] = env.split("=");
|
||||
envValue = envValue.join("=");
|
||||
let variable = null;
|
||||
if (foundTemplate?.variables) {
|
||||
variable = foundTemplate?.variables.find((v) => v.name === envKey) || foundTemplate?.variables.find((v) => v.id === envValue);
|
||||
}
|
||||
if (variable) {
|
||||
const id = variable.id.replaceAll("$$", "");
|
||||
const label = variable?.label;
|
||||
const description = variable?.description;
|
||||
const defaultValue = variable?.defaultValue;
|
||||
const main = variable?.main || "$$id";
|
||||
const type = variable?.type || "input";
|
||||
const placeholder = variable?.placeholder || "";
|
||||
const readOnly = variable?.readOnly || false;
|
||||
const required = variable?.required || false;
|
||||
if (envValue.startsWith("$$config") || variable?.showOnConfiguration) {
|
||||
if (envValue.startsWith("$$config_coolify")) {
|
||||
continue;
|
||||
}
|
||||
parsedTemplate[realKey].environment.push({
|
||||
id,
|
||||
name: envKey,
|
||||
value: envValue,
|
||||
main,
|
||||
label,
|
||||
description,
|
||||
defaultValue,
|
||||
type,
|
||||
placeholder,
|
||||
required,
|
||||
readOnly
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value?.proxy && value.proxy.length > 0) {
|
||||
for (const proxyValue of value.proxy) {
|
||||
if (proxyValue.domain) {
|
||||
const variable = foundTemplate?.variables.find((v) => v.id === proxyValue.domain);
|
||||
if (variable) {
|
||||
const { id, name: name2, label, description, defaultValue, required = false } = variable;
|
||||
const found = await import_prisma.prisma.serviceSetting.findFirst({
|
||||
where: { serviceId: service.id, variableName: proxyValue.domain }
|
||||
});
|
||||
parsedTemplate[realKey].fqdns.push({
|
||||
id,
|
||||
name: name2,
|
||||
value: found?.value || "",
|
||||
label,
|
||||
description,
|
||||
defaultValue,
|
||||
required
|
||||
});
|
||||
}
|
||||
}
|
||||
if (proxyValue.hostPort) {
|
||||
const variable = foundTemplate?.variables.find((v) => v.id === proxyValue.hostPort);
|
||||
if (variable) {
|
||||
const { id, name: name2, label, description, defaultValue, required = false } = variable;
|
||||
const found = await import_prisma.prisma.serviceSetting.findFirst({
|
||||
where: { serviceId: service.id, variableName: proxyValue.hostPort }
|
||||
});
|
||||
parsedTemplate[realKey].hostPorts.push({
|
||||
id,
|
||||
name: name2,
|
||||
value: found?.value || "",
|
||||
label,
|
||||
description,
|
||||
defaultValue,
|
||||
required
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parsedTemplate = foundTemplate;
|
||||
}
|
||||
let strParsedTemplate = JSON.stringify(parsedTemplate);
|
||||
strParsedTemplate = strParsedTemplate.replaceAll("$$id", service.id);
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(
|
||||
"$$core_version",
|
||||
service.version || foundTemplate.defaultVersion
|
||||
);
|
||||
if (workdir) {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll("$$workdir", workdir);
|
||||
}
|
||||
if (service.serviceSetting.length > 0) {
|
||||
for (const setting of service.serviceSetting) {
|
||||
const { value, variableName } = setting;
|
||||
const regex = new RegExp(`\\$\\$config_${variableName.replace("$$config_", "")}"`, "gi");
|
||||
if (value === "$$generate_fqdn") {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, service.fqdn + '"' || '"');
|
||||
} else if (value === "$$generate_fqdn_slash") {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, service.fqdn + '/"');
|
||||
} else if (value === "$$generate_domain") {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, (0, import_common.getDomain)(service.fqdn) + '"');
|
||||
} else if (service.destinationDocker?.network && value === "$$generate_network") {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(
|
||||
regex,
|
||||
service.destinationDocker.network + '"'
|
||||
);
|
||||
} else {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, value + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (service.serviceSecret.length > 0) {
|
||||
for (const secret of service.serviceSecret) {
|
||||
let { name, value } = secret;
|
||||
name = name.toLowerCase();
|
||||
const regexHashed = new RegExp(`\\$\\$hashed\\$\\$secret_${name}`, "gi");
|
||||
const regex = new RegExp(`\\$\\$secret_${name}`, "gi");
|
||||
if (value) {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(
|
||||
regexHashed,
|
||||
import_bcryptjs.default.hashSync(value.replaceAll('"', '\\"'), 10)
|
||||
);
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, value.replaceAll('"', '\\"'));
|
||||
} else {
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regexHashed, "");
|
||||
strParsedTemplate = strParsedTemplate.replaceAll(regex, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
parsedTemplate = JSON.parse(strParsedTemplate);
|
||||
}
|
||||
return parsedTemplate;
|
||||
}
|
||||
function generatePassword({
|
||||
length = 24,
|
||||
symbols = false,
|
||||
isHex = false
|
||||
}) {
|
||||
if (isHex) {
|
||||
return import_crypto.default.randomBytes(length).toString("hex");
|
||||
}
|
||||
const password = generator.generate({
|
||||
length,
|
||||
numbers: true,
|
||||
strict: true,
|
||||
symbols
|
||||
});
|
||||
return password;
|
||||
}
|
||||
async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddress }) {
|
||||
const { default: isReachable } = await import("is-port-reachable");
|
||||
const data = await import_prisma.prisma.setting.findFirst();
|
||||
const { minPort, maxPort } = data;
|
||||
if (remoteEngine) {
|
||||
const dbUsed = await (await import_prisma.prisma.database.findMany({
|
||||
where: {
|
||||
publicPort: { not: null },
|
||||
id: { not: id },
|
||||
destinationDocker: { remoteIpAddress }
|
||||
},
|
||||
select: { publicPort: true }
|
||||
})).map((a) => a.publicPort);
|
||||
const wpFtpUsed = await (await import_prisma.prisma.wordpress.findMany({
|
||||
where: {
|
||||
ftpPublicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { remoteIpAddress } }
|
||||
},
|
||||
select: { ftpPublicPort: true }
|
||||
})).map((a) => a.ftpPublicPort);
|
||||
const wpUsed = await (await import_prisma.prisma.wordpress.findMany({
|
||||
where: {
|
||||
mysqlPublicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { remoteIpAddress } }
|
||||
},
|
||||
select: { mysqlPublicPort: true }
|
||||
})).map((a) => a.mysqlPublicPort);
|
||||
const minioUsed = await (await import_prisma.prisma.minio.findMany({
|
||||
where: {
|
||||
publicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { remoteIpAddress } }
|
||||
},
|
||||
select: { publicPort: true }
|
||||
})).map((a) => a.publicPort);
|
||||
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
||||
const range = (0, import_common.generateRangeArray)(minPort, maxPort);
|
||||
const availablePorts = range.filter((port) => !usedPorts.includes(port));
|
||||
for (const port of availablePorts) {
|
||||
const found = await isReachable(port, { host: remoteIpAddress });
|
||||
if (!found) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
const dbUsed = await (await import_prisma.prisma.database.findMany({
|
||||
where: { publicPort: { not: null }, id: { not: id }, destinationDocker: { engine } },
|
||||
select: { publicPort: true }
|
||||
})).map((a) => a.publicPort);
|
||||
const wpFtpUsed = await (await import_prisma.prisma.wordpress.findMany({
|
||||
where: {
|
||||
ftpPublicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { engine } }
|
||||
},
|
||||
select: { ftpPublicPort: true }
|
||||
})).map((a) => a.ftpPublicPort);
|
||||
const wpUsed = await (await import_prisma.prisma.wordpress.findMany({
|
||||
where: {
|
||||
mysqlPublicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { engine } }
|
||||
},
|
||||
select: { mysqlPublicPort: true }
|
||||
})).map((a) => a.mysqlPublicPort);
|
||||
const minioUsed = await (await import_prisma.prisma.minio.findMany({
|
||||
where: {
|
||||
publicPort: { not: null },
|
||||
id: { not: id },
|
||||
service: { destinationDocker: { engine } }
|
||||
},
|
||||
select: { publicPort: true }
|
||||
})).map((a) => a.publicPort);
|
||||
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
|
||||
const range = (0, import_common.generateRangeArray)(minPort, maxPort);
|
||||
const availablePorts = range.filter((port) => !usedPorts.includes(port));
|
||||
for (const port of availablePorts) {
|
||||
const found = await isReachable(port, { host: "localhost" });
|
||||
if (!found) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async function verifyAndDecryptServiceSecrets(id) {
|
||||
const secrets = await import_prisma.prisma.serviceSecret.findMany({ where: { serviceId: id } });
|
||||
let decryptedSecrets = secrets.map((secret) => {
|
||||
const { name, value } = secret;
|
||||
if (value) {
|
||||
let rawValue = (0, import_common.decrypt)(value);
|
||||
rawValue = rawValue.replaceAll(/\$/gi, "$$$");
|
||||
return { name, value: rawValue };
|
||||
}
|
||||
return { name, value };
|
||||
});
|
||||
return decryptedSecrets;
|
||||
}
|
||||
function persistentVolumes(id, persistentStorage, config) {
|
||||
let volumeSet = /* @__PURE__ */ new Set();
|
||||
if (Object.keys(config).length > 0) {
|
||||
for (const [key, value] of Object.entries(config)) {
|
||||
if (value.volumes) {
|
||||
for (const volume of value.volumes) {
|
||||
if (!volume.startsWith("/")) {
|
||||
volumeSet.add(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const volumesArray = Array.from(volumeSet);
|
||||
const persistentVolume = persistentStorage?.map((storage) => {
|
||||
return `${id}${storage.path.replace(/\//gi, "-")}:${storage.path}`;
|
||||
}) || [];
|
||||
let volumes = [...persistentVolume];
|
||||
if (volumesArray)
|
||||
volumes = [...volumesArray, ...volumes];
|
||||
const composeVolumes = volumes.length > 0 && volumes.map((volume) => {
|
||||
return {
|
||||
[`${volume.split(":")[0]}`]: {
|
||||
name: volume.split(":")[0]
|
||||
}
|
||||
};
|
||||
}) || [];
|
||||
const volumeMounts = Object.assign({}, ...composeVolumes) || {};
|
||||
return { volumeMounts };
|
||||
}
|
||||
async function startServiceContainers(fastify, id, teamId, dockerId, composeFileDestination) {
|
||||
try {
|
||||
await (0, import_executeCommand.executeCommand)({ dockerId, command: `docker compose -f ${composeFileDestination} pull` });
|
||||
} catch (error) {
|
||||
}
|
||||
await (0, import_executeCommand.executeCommand)({ dockerId, command: `docker compose -f ${composeFileDestination} build --no-cache` });
|
||||
await (0, import_executeCommand.executeCommand)({ dockerId, command: `docker compose -f ${composeFileDestination} create` });
|
||||
await (0, import_executeCommand.executeCommand)({ dockerId, command: `docker compose -f ${composeFileDestination} start` });
|
||||
await (0, import_common.asyncSleep)(1e3);
|
||||
await (0, import_executeCommand.executeCommand)({ dockerId, command: `docker compose -f ${composeFileDestination} up -d` });
|
||||
}
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
generatePassword,
|
||||
getFreePublicPort,
|
||||
parseAndFindServiceTemplates,
|
||||
persistentVolumes,
|
||||
startServiceContainers,
|
||||
verifyAndDecryptServiceSecrets
|
||||
});
|
||||
Reference in New Issue
Block a user