Merge remote-tracking branch 'origin' into some-tweaks

This commit is contained in:
Kaname
2022-09-09 23:57:03 +00:00
23 changed files with 1040 additions and 946 deletions

View File

@@ -205,7 +205,7 @@ export async function isDNSValid(hostname: any, domain: string): Promise<any> {
const { isIP } = await import('is-ip');
const { DNSServers } = await listSettings();
if (DNSServers) {
dns.setServers([DNSServers]);
dns.setServers([...DNSServers.split(',')]);
}
let resolves = [];
try {
@@ -316,7 +316,7 @@ export async function checkDomainsIsValidInDNS({ hostname, fqdn, dualCerts }): P
const { DNSServers } = await listSettings();
if (DNSServers) {
dns.setServers([DNSServers]);
dns.setServers([...DNSServers.split(',')]);
}
let resolves = [];
@@ -547,22 +547,26 @@ export async function createRemoteEngineConfiguration(id: string) {
}
return await fs.writeFile(`${homedir}/.ssh/config`, sshConfig.stringify(config));
}
export async function executeDockerCmd({
debug,
buildId,
applicationId,
dockerId,
command
}: {
debug?: boolean;
buildId?: string;
applicationId?: string;
dockerId: string;
command: string;
}): Promise<any> {
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({
where: { id: dockerId }
});
export async function executeSSHCmd({ dockerId, command }) {
const { execaCommand } = await import('execa')
let { remoteEngine, remoteIpAddress, engine, remoteUser } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
if (remoteEngine) {
await createRemoteEngineConfiguration(dockerId)
engine = `ssh://${remoteIpAddress}`
} else {
engine = 'unix:///var/run/docker.sock'
}
if (process.env.CODESANDBOX_HOST) {
if (command.startsWith('docker compose')) {
command = command.replace(/docker compose/gi, 'docker-compose')
}
}
command = `ssh ${remoteIpAddress} ${command}`
return await execaCommand(command)
}
export async function executeDockerCmd({ debug, buildId, applicationId, dockerId, command }: { debug?: boolean, buildId?: string, applicationId?: string, dockerId: string, command: string }): Promise<any> {
const { execaCommand } = await import('execa')
let { remoteEngine, remoteIpAddress, engine, remoteUser } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
if (remoteEngine) {
await createRemoteEngineConfiguration(dockerId);
engine = `ssh://${remoteIpAddress}`;
@@ -577,7 +581,7 @@ export async function executeDockerCmd({
if (command.startsWith(`docker build --progress plain`)) {
return await asyncExecShellStream({ debug, buildId, applicationId, command, engine });
}
return await asyncExecShell(`DOCKER_BUILDKIT=1 DOCKER_HOST="${engine}" ${command}`);
return await execaCommand(command, { env: { DOCKER_BUILDKIT: "1", DOCKER_HOST: engine }, shell: true })
}
export async function startTraefikProxy(id: string): Promise<void> {
const { engine, network, remoteEngine, remoteIpAddress } =
@@ -822,7 +826,6 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
defaultDatabase,
version,
type,
settings: { appendOnly }
} = database;
const baseImage = getDatabaseImage(type, arch);
if (type === 'mysql') {
@@ -903,6 +906,7 @@ export function generateDatabaseConfiguration(database: any, arch: string): Data
}
return configuration;
} else if (type === 'redis') {
const { settings: { appendOnly } } = database;
const configuration: DatabaseConfiguration = {
privatePort: 6379,
command: undefined,
@@ -1182,113 +1186,150 @@ export async function updatePasswordInDb(database, user, newPassword, isRoot) {
}
}
}
export async function checkExposedPort({
id,
configuredPort,
exposePort,
dockerId,
remoteIpAddress
}: {
id: string;
configuredPort?: number;
exposePort: number;
dockerId: string;
remoteIpAddress?: string;
}) {
export async function checkExposedPort({ id, configuredPort, exposePort, engine, remoteEngine, remoteIpAddress }: { id: string, configuredPort?: number, exposePort: number, engine: string, remoteEngine: boolean, remoteIpAddress?: string }) {
if (exposePort < 1024 || exposePort > 65535) {
throw { status: 500, message: `Exposed Port needs to be between 1024 and 65535.` };
}
if (configuredPort) {
if (configuredPort !== exposePort) {
const availablePort = await getFreeExposedPort(id, exposePort, dockerId, remoteIpAddress);
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
if (availablePort.toString() !== exposePort.toString()) {
throw { status: 500, message: `Port ${exposePort} is already in use.` };
}
}
} else {
const availablePort = await getFreeExposedPort(id, exposePort, dockerId, remoteIpAddress);
const availablePort = await getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress);
if (availablePort.toString() !== exposePort.toString()) {
throw { status: 500, message: `Port ${exposePort} is already in use.` };
}
}
}
export async function getFreeExposedPort(id, exposePort, dockerId, remoteIpAddress) {
export async function getFreeExposedPort(id, exposePort, engine, remoteEngine, remoteIpAddress) {
const { default: checkPort } = await import('is-port-reachable');
const applicationUsed = await (
await prisma.application.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDockerId: dockerId },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const serviceUsed = await (
await prisma.service.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDockerId: dockerId },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const usedPorts = [...applicationUsed, ...serviceUsed];
if (usedPorts.includes(exposePort)) {
return false;
if (remoteEngine) {
const applicationUsed = await (
await prisma.application.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const serviceUsed = await (
await prisma.service.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const usedPorts = [...applicationUsed, ...serviceUsed];
if (usedPorts.includes(exposePort)) {
return false
}
const found = await checkPort(exposePort, { host: remoteIpAddress });
if (!found) {
return exposePort
}
return false
} else {
const applicationUsed = await (
await prisma.application.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { engine } },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const serviceUsed = await (
await prisma.service.findMany({
where: { exposePort: { not: null }, id: { not: id }, destinationDocker: { engine } },
select: { exposePort: true }
})
).map((a) => a.exposePort);
const usedPorts = [...applicationUsed, ...serviceUsed];
if (usedPorts.includes(exposePort)) {
return false
}
const found = await checkPort(exposePort, { host: 'localhost' });
if (!found) {
return exposePort
}
return false
}
const found = await checkPort(exposePort, { host: remoteIpAddress || 'localhost' });
if (!found) {
return exposePort;
}
return false;
}
export function generateRangeArray(start, end) {
return Array.from({ length: end - start }, (v, k) => k + start);
}
export async function getFreePublicPort(id, dockerId) {
export async function getFreePublicPort({ id, remoteEngine, engine, remoteIpAddress }) {
const { default: isReachable } = await import('is-port-reachable');
const data = await prisma.setting.findFirst();
const { minPort, maxPort } = data;
const dbUsed = await (
await prisma.database.findMany({
where: { publicPort: { not: null }, id: { not: id }, destinationDockerId: dockerId },
select: { publicPort: true }
})
).map((a) => a.publicPort);
const wpFtpUsed = await (
await prisma.wordpress.findMany({
where: {
ftpPublicPort: { not: null },
id: { not: id },
service: { destinationDockerId: dockerId }
},
select: { ftpPublicPort: true }
})
).map((a) => a.ftpPublicPort);
const wpUsed = await (
await prisma.wordpress.findMany({
where: {
mysqlPublicPort: { not: null },
id: { not: id },
service: { destinationDockerId: dockerId }
},
select: { mysqlPublicPort: true }
})
).map((a) => a.mysqlPublicPort);
const minioUsed = await (
await prisma.minio.findMany({
where: {
publicPort: { not: null },
id: { not: id },
service: { destinationDockerId: dockerId }
},
select: { publicPort: true }
})
).map((a) => a.publicPort);
const usedPorts = [...dbUsed, ...wpFtpUsed, ...wpUsed, ...minioUsed];
const range = 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;
if (remoteEngine) {
const dbUsed = await (
await prisma.database.findMany({
where: { publicPort: { not: null }, id: { not: id }, destinationDocker: { remoteIpAddress } },
select: { publicPort: true }
})
).map((a) => a.publicPort);
const wpFtpUsed = await (
await prisma.wordpress.findMany({
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
select: { ftpPublicPort: true }
})
).map((a) => a.ftpPublicPort);
const wpUsed = await (
await prisma.wordpress.findMany({
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { remoteIpAddress } } },
select: { mysqlPublicPort: true }
})
).map((a) => a.mysqlPublicPort);
const minioUsed = await (
await 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 = 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 prisma.database.findMany({
where: { publicPort: { not: null }, id: { not: id }, destinationDocker: { engine } },
select: { publicPort: true }
})
).map((a) => a.publicPort);
const wpFtpUsed = await (
await prisma.wordpress.findMany({
where: { ftpPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
select: { ftpPublicPort: true }
})
).map((a) => a.ftpPublicPort);
const wpUsed = await (
await prisma.wordpress.findMany({
where: { mysqlPublicPort: { not: null }, id: { not: id }, service: { destinationDocker: { engine } } },
select: { mysqlPublicPort: true }
})
).map((a) => a.mysqlPublicPort);
const minioUsed = await (
await 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 = 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
}
return false;
}
export async function startTraefikTCPProxy(

View File

@@ -321,8 +321,8 @@ async function startMinioService(request: FastifyRequest<ServiceStartStop>) {
const network = destinationDockerId && destinationDocker.network;
const port = getServiceMainPort('minio');
const { service: { destinationDocker: { id: dockerId } } } = await prisma.minio.findUnique({ where: { serviceId: id }, include: { service: { include: { destinationDocker: true } } } })
const publicPort = await getFreePublicPort(id, dockerId);
const { service: { destinationDocker: { remoteEngine, engine, remoteIpAddress } } } = await prisma.minio.findUnique({ where: { serviceId: id }, include: { service: { include: { destinationDocker: true } } } })
const publicPort = await getFreePublicPort({ id, remoteEngine, engine, remoteIpAddress });
const consolePort = 9001;
const { workdir } = await createDirectories({ repository: type, buildId: id });
@@ -1979,8 +1979,8 @@ async function startGlitchTipService(request: FastifyRequest<ServiceStartStop>)
EMAIL_PORT: emailSmtpPort,
EMAIL_HOST_USER: emailSmtpUser,
EMAIL_HOST_PASSWORD: emailSmtpPassword,
EMAIL_USE_TLS: emailSmtpUseTls,
EMAIL_USE_SSL: emailSmtpUseSsl,
EMAIL_USE_TLS: emailSmtpUseTls ? 'True' : 'False',
EMAIL_USE_SSL: emailSmtpUseSsl ? 'True' : 'False',
EMAIL_BACKEND: emailBackend,
MAILGUN_API_KEY: mailgunApiKey,
SENDGRID_API_KEY: sendgridApiKey,