mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-29 12:33:59 +00:00
v1.0.12 - Sveltekit migration (#44)
Changed the whole tech stack to SvelteKit which means: - Typescript - SSR - No fastify :( - Beta, but it's fine! Other changes: - Tailwind -> Tailwind JIT - A lot more
This commit is contained in:
122
src/routes/api/v1/databases/[deployId]/backup.ts
Normal file
122
src/routes/api/v1/databases/[deployId]/backup.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
import { saveServerLog } from '$lib/api/applications/logging';
|
||||
import { execShellAsync } from '$lib/api/common';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import fs from 'fs';
|
||||
|
||||
export async function post(request: Request) {
|
||||
const tmpdir = '/tmp/backups';
|
||||
const { deployId } = request.params;
|
||||
try {
|
||||
const now = new Date();
|
||||
const configuration = JSON.parse(
|
||||
JSON.parse(await execShellAsync(`docker inspect ${deployId}_${deployId}`))[0].Spec.Labels
|
||||
.configuration
|
||||
);
|
||||
const type = configuration.general.type;
|
||||
const serviceId = configuration.general.deployId;
|
||||
const databaseService = (await docker.engine.listContainers()).find(
|
||||
(r) => r.Labels['com.docker.stack.namespace'] === serviceId && r.State === 'running'
|
||||
);
|
||||
const containerID = databaseService.Labels['com.docker.swarm.task.name'];
|
||||
await execShellAsync(`mkdir -p ${tmpdir}`);
|
||||
if (type === 'mongodb') {
|
||||
if (databaseService) {
|
||||
const username = configuration.database.usernames[0];
|
||||
const password = configuration.database.passwords[1];
|
||||
const databaseName = configuration.database.defaultDatabaseName;
|
||||
const filename = `${databaseName}_${now.getTime()}.gz`;
|
||||
const fullfilename = `${tmpdir}/${filename}`;
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "mkdir -p ${tmpdir};mongodump --uri='mongodb://${username}:${password}@${deployId}:27017' -d ${databaseName} --gzip --archive=${fullfilename}"`
|
||||
);
|
||||
await execShellAsync(`docker cp ${containerID}:${fullfilename} ${fullfilename}`);
|
||||
await execShellAsync(`docker exec -i ${containerID} /bin/bash -c "rm -f ${fullfilename}"`);
|
||||
return {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Transfer-Encoding': 'binary',
|
||||
'Content-Disposition': `attachment; filename=${filename}`
|
||||
},
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
} else if (type === 'postgresql') {
|
||||
if (databaseService) {
|
||||
const username = configuration.database.usernames[0];
|
||||
const password = configuration.database.passwords[0];
|
||||
const databaseName = configuration.database.defaultDatabaseName;
|
||||
const filename = `${databaseName}_${now.getTime()}.sql.gz`;
|
||||
const fullfilename = `${tmpdir}/${filename}`;
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "PGPASSWORD=${password} pg_dump --username ${username} -Z 9 ${databaseName}" > ${fullfilename}`
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Transfer-Encoding': 'binary',
|
||||
'Content-Disposition': `attachment; filename=${filename}`
|
||||
},
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
} else if (type === 'couchdb') {
|
||||
if (databaseService) {
|
||||
const databaseName = configuration.database.defaultDatabaseName;
|
||||
const filename = `${databaseName}_${now.getTime()}.tar.gz`;
|
||||
const fullfilename = `${tmpdir}/${filename}`;
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "cd /bitnami/couchdb/data/ && tar -czvf - ." > ${fullfilename}`
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Transfer-Encoding': 'binary',
|
||||
'Content-Disposition': `attachment; filename=${filename}`
|
||||
},
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
} else if (type === 'mysql') {
|
||||
if (databaseService) {
|
||||
const username = configuration.database.usernames[0];
|
||||
const password = configuration.database.passwords[0];
|
||||
const databaseName = configuration.database.defaultDatabaseName;
|
||||
const filename = `${databaseName}_${now.getTime()}.sql.gz`;
|
||||
const fullfilename = `${tmpdir}/${filename}`;
|
||||
await execShellAsync(
|
||||
`docker exec -i ${containerID} /bin/bash -c "mysqldump -u ${username} -p${password} ${databaseName} | gzip -9 -" > ${fullfilename}`
|
||||
);
|
||||
return {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-Transfer-Encoding': 'binary',
|
||||
'Content-Disposition': `attachment; filename=${filename}`
|
||||
},
|
||||
body: fs.readFileSync(`${fullfilename}`)
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: 501,
|
||||
body: {
|
||||
error: `Backup method not implemented yet for ${type}.`
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
await saveServerLog(error);
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
await execShellAsync(`rm -fr ${tmpdir}`);
|
||||
}
|
||||
}
|
||||
59
src/routes/api/v1/databases/[deployId]/index.ts
Normal file
59
src/routes/api/v1/databases/[deployId]/index.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { execShellAsync } from '$lib/api/common';
|
||||
import { docker } from '$lib/api/docker';
|
||||
import type { Request } from '@sveltejs/kit';
|
||||
|
||||
export async function del(request: Request) {
|
||||
const { deployId } = request.params;
|
||||
await execShellAsync(`docker stack rm ${deployId}`);
|
||||
return {
|
||||
status: 200,
|
||||
body: {}
|
||||
};
|
||||
}
|
||||
export async function get(request: Request) {
|
||||
const { deployId } = request.params;
|
||||
|
||||
try {
|
||||
const database = (await docker.engine.listServices()).find(
|
||||
(r) =>
|
||||
r.Spec.Labels.managedBy === 'coolify' &&
|
||||
r.Spec.Labels.type === 'database' &&
|
||||
JSON.parse(r.Spec.Labels.configuration).general.deployId === deployId
|
||||
);
|
||||
|
||||
if (database) {
|
||||
const jsonEnvs = {};
|
||||
if (database.Spec.TaskTemplate.ContainerSpec.Env) {
|
||||
for (const d of database.Spec.TaskTemplate.ContainerSpec.Env) {
|
||||
const s = d.split('=');
|
||||
jsonEnvs[s[0]] = s[1];
|
||||
}
|
||||
}
|
||||
const payload = {
|
||||
config: JSON.parse(database.Spec.Labels.configuration),
|
||||
envs: jsonEnvs || null
|
||||
};
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
...payload
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'No database found.'
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'No database found.'
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user