feat(frontend): rclone repositories config

This commit is contained in:
Nicolas Meienberger
2025-11-11 21:31:10 +01:00
parent 8f9873148a
commit 36b0282d18
10 changed files with 265 additions and 43 deletions

View File

@@ -39,6 +39,21 @@ export const repositoriesController = new Hono()
return c.json({ message: "Repository created", repository: res.repository }, 201);
})
.get("/rclone-remotes", listRcloneRemotesDto, async (c) => {
const remoteNames = await listRcloneRemotes();
const remotes = await Promise.all(
remoteNames.map(async (name) => {
const info = await getRcloneRemoteInfo(name);
return {
name,
type: info?.type ?? "unknown",
};
}),
);
return c.json(remotes);
})
.get("/:name", getRepositoryDto, async (c) => {
const { name } = c.req.param();
const res = await repositoriesService.getRepository(name);
@@ -127,19 +142,4 @@ export const repositoriesController = new Hono()
const result = await repositoriesService.doctorRepository(name);
return c.json<DoctorRepositoryDto>(result, 200);
})
.get("/rclone-remotes", listRcloneRemotesDto, async (c) => {
const remoteNames = await listRcloneRemotes();
const remotes = await Promise.all(
remoteNames.map(async (name) => {
const info = await getRcloneRemoteInfo(name);
return {
name,
type: info?.type ?? "unknown",
};
}),
);
return c.json(remotes);
});

View File

@@ -6,27 +6,22 @@ import { logger } from "./logger";
* @returns Array of remote names
*/
export async function listRcloneRemotes(): Promise<string[]> {
try {
const result = await $`rclone listremotes`.quiet();
const result = await $`rclone listremotes`.nothrow();
if (result.exitCode !== 0) {
logger.error(`Failed to list rclone remotes: ${result.stderr}`);
return [];
}
// Parse output - each line is a remote name ending with ":"
const remotes = result.stdout
.toString()
.split("\n")
.map((line) => line.trim())
.filter((line) => line.endsWith(":"))
.map((line) => line.slice(0, -1)); // Remove trailing ":"
return remotes;
} catch (error) {
logger.error(`Error listing rclone remotes: ${error}`);
if (result.exitCode !== 0) {
logger.error(`Failed to list rclone remotes: ${result.stderr}`);
return [];
}
// Parse output - each line is a remote name ending with ":"
const remotes = result.stdout
.toString()
.split("\n")
.map((line) => line.trim())
.filter((line) => line.endsWith(":"))
.map((line) => line.slice(0, -1)); // Remove trailing ":"
return remotes;
}
/**

View File

@@ -90,6 +90,7 @@ const buildEnv = async (config: RepositoryConfig) => {
const env: Record<string, string> = {
RESTIC_CACHE_DIR: "/var/lib/ironmount/restic/cache",
RESTIC_PASSWORD_FILE: RESTIC_PASS_FILE,
PATH: process.env.PATH || "/usr/local/bin:/usr/bin:/bin",
};
switch (config.backend) {
@@ -234,6 +235,8 @@ const backup = async (
if (res.exitCode !== 0) {
logger.error(`Restic backup failed: ${res.stderr}`);
logger.error(`Command executed: restic ${args.join(" ")}`);
throw new Error(`Restic backup failed: ${res.stderr}`);
}
@@ -361,7 +364,7 @@ const snapshots = async (config: RepositoryConfig, options: { tags?: string[] }
args.push("--json");
const res = await $`restic ${args}`.env(env).nothrow();
const res = await $`restic ${args}`.env(env).nothrow().quiet();
if (res.exitCode !== 0) {
logger.error(`Restic snapshots retrieval failed: ${res.stderr}`);
@@ -456,7 +459,7 @@ const ls = async (config: RepositoryConfig, snapshotId: string, path?: string) =
args.push(path);
}
const res = await $`restic ${args}`.env(env).nothrow();
const res = await $`restic ${args}`.env(env).nothrow().quiet();
if (res.exitCode !== 0) {
logger.error(`Restic ls failed: ${res.stderr}`);