Files
coolify/src/routes/api/v1/databases/[deployId]/backup.ts
Andras Bacsai adcd68c1ab v1.0.13 (#46)
2021-05-16 21:54:44 +02:00

147 lines
5.3 KiB
TypeScript

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}`)
};
}
} else if (type === 'redis') {
if (databaseService) {
const password = configuration.database.passwords[0];
const databaseName = configuration.database.defaultDatabaseName;
const filename = `${databaseName}_${now.getTime()}.rdb`;
const fullfilename = `${tmpdir}/${filename}`;
await execShellAsync(
`docker exec -i ${containerID} /bin/bash -c "redis-cli --pass ${password} save"`
);
await execShellAsync(
`docker cp ${containerID}:/bitnami/redis/data/dump.rdb ${fullfilename}`
);
await execShellAsync(
`docker exec -i ${containerID} /bin/bash -c "rm -f /bitnami/redis/data/dump.rdb"`
);
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) {
await saveServerLog(error);
return {
status: 500,
body: {
error: error.message || error
}
};
} finally {
await execShellAsync(`rm -fr ${tmpdir}`);
}
}