fix(volumes): isolate test-connection mounts in temp directories

This commit is contained in:
Nicolas Meienberger 2026-04-20 22:28:42 +02:00
parent 8ece1ef187
commit 694f1c212f
No known key found for this signature in database
3 changed files with 36 additions and 11 deletions

View file

@ -19,27 +19,25 @@ export type VolumeBackend = {
checkHealth: () => Promise<OperationResult>;
};
export const createVolumeBackend = (volume: Volume): VolumeBackend => {
const path = getVolumePath(volume);
export const createVolumeBackend = (volume: Volume, mountPath = getVolumePath(volume)): VolumeBackend => {
switch (volume.config.backend) {
case "nfs": {
return makeNfsBackend(volume.config, path);
return makeNfsBackend(volume.config, mountPath);
}
case "smb": {
return makeSmbBackend(volume.config, path);
return makeSmbBackend(volume.config, mountPath);
}
case "directory": {
return makeDirectoryBackend(volume.config, path);
return makeDirectoryBackend(volume.config, mountPath);
}
case "webdav": {
return makeWebdavBackend(volume.config, path);
return makeWebdavBackend(volume.config, mountPath);
}
case "rclone": {
return makeRcloneBackend(volume.config, path);
return makeRcloneBackend(volume.config, mountPath);
}
case "sftp": {
return makeSftpBackend(volume.config, path);
return makeSftpBackend(volume.config, mountPath);
}
default: {
throw new Error("Unsupported backend");

View file

@ -211,3 +211,31 @@ describe("volumeService.ensureHealthyVolume", () => {
});
});
});
describe("volumeService.testConnection", () => {
test("uses an isolated temp mount path for backend test connections", async () => {
const mount = vi.fn().mockResolvedValue({ status: "mounted" });
const unmount = vi.fn().mockResolvedValue({ status: "unmounted" });
const createVolumeBackendSpy = vi.spyOn(backendModule, "createVolumeBackend").mockReturnValue({
mount,
unmount,
checkHealth: vi.fn(),
});
await volumeService.testConnection({
backend: "nfs",
server: "127.0.0.1",
exportPath: "/exports/test",
version: "4",
port: 2049,
readOnly: false,
});
expect(createVolumeBackendSpy).toHaveBeenCalledOnce();
const [, mountPath] = createVolumeBackendSpy.mock.calls[0];
expect(mountPath).toEqual(expect.stringContaining(`${path.sep}zerobyte-test-`));
await expect(fs.access(mountPath as string)).rejects.toThrow();
expect(mount).toHaveBeenCalledOnce();
expect(unmount).toHaveBeenCalledOnce();
});
});

View file

@ -237,7 +237,6 @@ const testConnection = async (backendConfig: BackendConfig) => {
id: 0,
shortId: asShortId("test"),
name: "test-connection",
path: tempDir,
config: encryptedConfig,
createdAt: Date.now(),
updatedAt: Date.now(),
@ -250,7 +249,7 @@ const testConnection = async (backendConfig: BackendConfig) => {
organizationId: "test-org",
};
const backend = createVolumeBackend(mockVolume);
const backend = createVolumeBackend(mockVolume, tempDir);
const { error } = await backend.mount();
await backend.unmount();