This commit is contained in:
Andras Bacsai
2022-10-28 15:50:57 +02:00
parent 781fd0a1cd
commit c123669828
14 changed files with 198 additions and 62 deletions

View File

@@ -6,6 +6,8 @@ import cookie from '@fastify/cookie';
import multipart from '@fastify/multipart';
import path, { join } from 'path';
import autoLoad from '@fastify/autoload';
import websocket from '@fastify/websocket';
import { asyncExecShell, cleanupDockerStorage, createRemoteEngineConfiguration, decrypt, encrypt, executeDockerCmd, executeSSHCmd, generateDatabaseConfiguration, getDomain, isDev, listSettings, prisma, startTraefikProxy, startTraefikTCPProxy, version } from './lib/common';
import { scheduler } from './lib/scheduler';
import { compareVersions } from 'compare-versions';
@@ -16,6 +18,8 @@ import { verifyRemoteDockerEngineFn } from './routes/api/v1/destinations/handler
import { checkContainer } from './lib/docker';
import { migrateServicesToNewTemplate } from './lib';
import { refreshTags, refreshTemplates } from './routes/api/v1/handlers';
import { realtime } from './routes/realtime';
import cuid from 'cuid';
declare module 'fastify' {
interface FastifyInstance {
config: {
@@ -105,6 +109,23 @@ const host = '0.0.0.0';
});
fastify.register(cookie)
fastify.register(cors);
fastify.register(websocket, {
options: {
clientTracking: true,
verifyClient: async (info, next) => {
try {
const token = info.req.headers?.cookie.split('; ').find((cookie) => cookie.startsWith('token')).split('=')[1];
if (!token) {
return next(false)
}
fastify.jwt.verify(token)
} catch (error) {
return next(false)
}
next(true)
}
}
})
// To detect allowed origins
// fastify.addHook('onRequest', async (request, reply) => {
// let allowedList = ['coolify:3000'];
@@ -127,6 +148,19 @@ const host = '0.0.0.0';
try {
fastify.decorate('wssend', function (data: any) {
fastify.websocketServer.clients.forEach((client) => {
client.send(JSON.stringify(data));
})
})
fastify.register(async function (fastify) {
fastify.get('/realtime', { websocket: true }, (connection) => {
// connection.socket.on('message', message => {
// realtime(fastify, connection, message)
// })
})
})
await fastify.listen({ port, host })
console.log(`Coolify's API is listening on ${host}:${port}`);

View File

@@ -293,28 +293,47 @@ async function ghost(service: any, template: any) {
async function wordpress(service: any, template: any) {
const { extraConfig, tablePrefix, ownMysql, mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlRootUser, mysqlRootUserPassword, mysqlDatabase, ftpEnabled, ftpUser, ftpPassword, ftpPublicPort, ftpHostKey, ftpHostKeyPrivate } = service.wordpress
const secrets = [
`MYSQL_ROOT_PASSWORD@@@${mysqlRootUserPassword}`,
`MYSQL_PASSWORD@@@${mysqlPassword}`,
ftpPassword && `COOLIFY_FTP_PASSWORD@@@${ftpPassword}`,
ftpHostKeyPrivate && `COOLIFY_FTP_HOST_KEY_PRIVATE@@@${ftpHostKeyPrivate}`,
ftpHostKey && `COOLIFY_FTP_HOST_KEY@@@${ftpHostKey}`,
]
const settings = [
`MYSQL_ROOT_USER@@@${mysqlRootUser}`,
`MYSQL_USER@@@${mysqlUser}`,
`MYSQL_DATABASE@@@${mysqlDatabase}`,
`MYSQL_HOST@@@${ownMysql ? mysqlHost : `${service.id}-mysql`}`,
`MYSQL_PORT@@@${mysqlPort}`,
`WORDPRESS_CONFIG_EXTRA@@@${extraConfig}`,
`WORDPRESS_TABLE_PREFIX@@@${tablePrefix}`,
`WORDPRESS_DB_HOST@@@${ownMysql ? mysqlHost : `${service.id}-mysql`}`,
`COOLIFY_OWN_DB@@@${ownMysql}`,
`COOLIFY_FTP_ENABLED@@@${ftpEnabled}`,
`COOLIFY_FTP_USER@@@${ftpUser}`,
`COOLIFY_FTP_PUBLIC_PORT@@@${ftpPublicPort}`,
]
let settings = []
let secrets = []
if (ownMysql) {
secrets = [
`WORDPRESS_DB_PASSWORD@@@${mysqlPassword}`,
ftpPassword && `COOLIFY_FTP_PASSWORD@@@${ftpPassword}`,
ftpHostKeyPrivate && `COOLIFY_FTP_HOST_KEY_PRIVATE@@@${ftpHostKeyPrivate}`,
ftpHostKey && `COOLIFY_FTP_HOST_KEY@@@${ftpHostKey}`,
]
settings = [
`WORDPRESS_CONFIG_EXTRA@@@${extraConfig}`,
`WORDPRESS_DB_HOST@@@${mysqlHost}`,
`WORDPRESS_DB_PORT@@@${mysqlPort}`,
`WORDPRESS_DB_USER@@@${mysqlUser}`,
`WORDPRESS_DB_NAME@@@${mysqlDatabase}`,
]
} else {
secrets = [
`MYSQL_ROOT_PASSWORD@@@${mysqlRootUserPassword}`,
`MYSQL_PASSWORD@@@${mysqlPassword}`,
ftpPassword && `COOLIFY_FTP_PASSWORD@@@${ftpPassword}`,
ftpHostKeyPrivate && `COOLIFY_FTP_HOST_KEY_PRIVATE@@@${ftpHostKeyPrivate}`,
ftpHostKey && `COOLIFY_FTP_HOST_KEY@@@${ftpHostKey}`,
]
settings = [
`MYSQL_ROOT_USER@@@${mysqlRootUser}`,
`MYSQL_USER@@@${mysqlUser}`,
`MYSQL_DATABASE@@@${mysqlDatabase}`,
`MYSQL_HOST@@@${service.id}-mysql`,
`MYSQL_PORT@@@${mysqlPort}`,
`WORDPRESS_CONFIG_EXTRA@@@${extraConfig}`,
`WORDPRESS_TABLE_PREFIX@@@${tablePrefix}`,
`WORDPRESS_DB_HOST@@@${service.id}-mysql`,
`COOLIFY_OWN_DB@@@${ownMysql}`,
`COOLIFY_FTP_ENABLED@@@${ftpEnabled}`,
`COOLIFY_FTP_USER@@@${ftpUser}`,
`COOLIFY_FTP_PUBLIC_PORT@@@${ftpPublicPort}`,
]
}
await migrateSettings(settings, service, template);
await migrateSecrets(secrets, service);
if (ownMysql) {

View File

@@ -29,7 +29,7 @@ export async function stopService(request: FastifyRequest<ServiceStartStop>) {
return errorHandler({ status, message })
}
}
export async function startService(request: FastifyRequest<ServiceStartStop>) {
export async function startService(request: FastifyRequest<ServiceStartStop>, fastify: any) {
try {
const { id } = request.params;
const teamId = request.user.teamId;
@@ -42,12 +42,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
const template: any = await parseAndFindServiceTemplates(service, workdir, true)
const network = destinationDockerId && destinationDocker.network;
const config = {};
const isWordpress = type === 'wordpress';
for (const s in template.services) {
if (isWordpress && service.wordpress.ownMysql && s.name === 'MySQL') {
console.log('skipping predefined mysql')
continue;
}
let newEnvironments = []
if (arm) {
if (template.services[s]?.environmentArm?.length > 0) {
@@ -90,23 +85,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
}
}
}
if (isWordpress) {
const { wordpress: { mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlDatabase, ownMysql } } = service
console.log({ mysqlHost, mysqlPort, mysqlUser, mysqlPassword, mysqlDatabase, ownMysql })
if (ownMysql) {
let envsToRemove = ['WORDPRESS_DB_HOST', 'WORDPRESS_DB_USER', 'WORDPRESS_DB_PASSWORD', 'WORDPRESS_DB_NAME']
for (const env of newEnvironments) {
if (envsToRemove.includes(env.split('=')[0])) {
console.log('removing', env)
newEnvironments = newEnvironments.filter(e => e !== env)
}
}
newEnvironments.push(`WORDPRESS_DB_HOST=${mysqlHost}:${mysqlPort}`)
newEnvironments.push(`WORDPRESS_DB_USER=${mysqlUser}`)
newEnvironments.push(`WORDPRESS_DB_PASSWORD=${mysqlPassword}`)
newEnvironments.push(`WORDPRESS_DB_NAME=${mysqlDatabase}`)
}
}
config[s] = {
container_name: s,
build: template.services[s].build || undefined,
@@ -141,7 +120,7 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
Dockerfile += `
COPY ./${path.basename(source)} ${destination}`
}
await fs.writeFile(`${workdir}/Dockerfile.${servsice}`, Dockerfile);
await fs.writeFile(`${workdir}/Dockerfile.${service}`, Dockerfile);
}
}
const { volumeMounts } = persistentVolumes(id, persistentStorage, config)
@@ -157,21 +136,26 @@ export async function startService(request: FastifyRequest<ServiceStartStop>) {
}
const composeFileDestination = `${workdir}/docker-compose.yaml`;
await fs.writeFile(composeFileDestination, yaml.dump(composeFile));
await startServiceContainers(destinationDocker.id, composeFileDestination)
await startServiceContainers(fastify, id, teamId, destinationDocker.id, composeFileDestination)
return {}
} catch ({ status, message }) {
return errorHandler({ status, message })
}
}
async function startServiceContainers(dockerId, composeFileDestination) {
async function startServiceContainers(fastify, id, teamId, dockerId, composeFileDestination) {
try {
fastify.wssend({ teamId, type: 'service', id, message: 'Pulling images...' })
await executeDockerCmd({ dockerId, command: `docker compose -f ${composeFileDestination} pull` })
} catch (error) { }
fastify.wssend({ teamId, type: 'service', id, message: 'Building...' })
await executeDockerCmd({ dockerId, command: `docker compose -f ${composeFileDestination} build --no-cache` })
fastify.wssend({ teamId, type: 'service', id, message: 'Creating containers...' })
await executeDockerCmd({ dockerId, command: `docker compose -f ${composeFileDestination} create` })
fastify.wssend({ teamId, type: 'service', id, message: 'Starting containers...' })
await executeDockerCmd({ dockerId, command: `docker compose -f ${composeFileDestination} start` })
await asyncSleep(1000);
await executeDockerCmd({ dockerId, command: `docker compose -f ${composeFileDestination} up -d` })
fastify.wssend({ teamId, type: 'service', id, message: 'ending' })
}
export async function migrateAppwriteDB(request: FastifyRequest<OnlyId>, reply: FastifyReply) {
try {

View File

@@ -1,9 +1,6 @@
import { FastifyPluginAsync } from 'fastify';
import { checkUpdate, login, showDashboard, update, resetQueue, getCurrentUser, cleanupManually, restartCoolify, refreshTemplates } from './handlers';
import { GetCurrentUser } from './types';
import pump from 'pump'
import fs from 'fs'
import { asyncExecShell, encrypt, errorHandler, prisma } from '../../../lib/common';
export interface Update {
Body: { latestVersion: string }

View File

@@ -70,7 +70,7 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
fastify.get<OnlyId>('/:id/usage', async (request) => await getServiceUsage(request));
fastify.get<GetServiceLogs>('/:id/logs/:containerId', async (request) => await getServiceLogs(request));
fastify.post<ServiceStartStop>('/:id/start', async (request) => await startService(request));
fastify.post<ServiceStartStop>('/:id/start', async (request) => await startService(request, fastify));
fastify.post<ServiceStartStop>('/:id/stop', async (request) => await stopService(request));
fastify.post<ServiceStartStop & SetWordpressSettings & SetGlitchTipSettings>('/:id/:type/settings', async (request, reply) => await setSettingsService(request, reply));

View File

@@ -0,0 +1,7 @@
export function realtime(fastify, connection, message) {
const { socket } = connection
const data = JSON.parse(message);
if (data.type === 'subscribe') {
socket.send(JSON.stringify({ type: 'subscribe', message: 'pong' }))
}
}