mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 14:15:24 +00:00
feat: finish the docker plugin (B15)
This commit is contained in:
1 parent
0a3f05d99d
commit
993a91c899
167 files changed
+26299
-5136
No files matched your search
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* The Docker host settings migration.
|
||||
*
|
||||
* An upgrade must be lossless: every host with Docker on, and every host on
|
||||
* Podman, must come through into the docker plugin's host settings, whatever
|
||||
* shape the engine returned the flag in. Running it twice must not duplicate
|
||||
* or clobber what it moved.
|
||||
*/
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const state = vi.hoisted(() => ({
|
||||
pluginRows: [] as Array<{
|
||||
pluginId: string;
|
||||
scope: string;
|
||||
scopeId: string | null;
|
||||
key: string;
|
||||
value: string | null;
|
||||
}>,
|
||||
hostRows: [] as Array<Record<string, unknown>>,
|
||||
pluginInstalled: true,
|
||||
columnsGone: false,
|
||||
}));
|
||||
|
||||
vi.mock("../../database/repositories/factory.js", () => ({
|
||||
createCurrentPluginRepository: () => ({
|
||||
findById: async (id: string) =>
|
||||
state.pluginInstalled && id === "docker" ? { id } : null,
|
||||
}),
|
||||
createCurrentPluginSettingsRepository: () => ({
|
||||
getAll: async (_pluginId: string, scope: string, scopeId: string | null) =>
|
||||
state.pluginRows.filter(
|
||||
(row) => row.scope === scope && row.scopeId === scopeId,
|
||||
),
|
||||
set: async (
|
||||
pluginId: string,
|
||||
scope: string,
|
||||
scopeId: string | null,
|
||||
key: string,
|
||||
value: string | null,
|
||||
) => {
|
||||
const existing = state.pluginRows.find(
|
||||
(row) =>
|
||||
row.scope === scope && row.scopeId === scopeId && row.key === key,
|
||||
);
|
||||
if (existing) {
|
||||
existing.value = value;
|
||||
return;
|
||||
}
|
||||
state.pluginRows.push({ pluginId, scope, scopeId, key, value });
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/crypto-migration/raw-rows.js", () => ({
|
||||
selectRows: async () => {
|
||||
if (state.columnsGone) throw new Error("no such column: enable_docker");
|
||||
return state.hostRows;
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../../utils/logger.js", () => ({
|
||||
databaseLogger: { info: vi.fn(), warn: vi.fn() },
|
||||
}));
|
||||
|
||||
import {
|
||||
dockerSettingsFromRow,
|
||||
runDockerSettingsMigration,
|
||||
} from "../../utils/crypto-migration/docker-settings-migration.js";
|
||||
|
||||
const hostValues = (hostId: number) =>
|
||||
Object.fromEntries(
|
||||
state.pluginRows
|
||||
.filter((row) => row.scope === "host" && row.scopeId === String(hostId))
|
||||
.map((row) => [row.key, JSON.parse(row.value ?? "null")]),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
state.pluginRows = [];
|
||||
state.hostRows = [];
|
||||
state.pluginInstalled = true;
|
||||
state.columnsGone = false;
|
||||
});
|
||||
|
||||
describe("dockerSettingsFromRow", () => {
|
||||
it("reads SQLite integers, real booleans and strings", () => {
|
||||
expect(
|
||||
dockerSettingsFromRow({ id: 1, enable_docker: 1, docker_config: null }),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: true,
|
||||
docker_config: null,
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({ id: 1, enable_docker: 0, docker_config: null }),
|
||||
).toEqual({});
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: false,
|
||||
docker_config: null,
|
||||
}),
|
||||
).toEqual({});
|
||||
});
|
||||
|
||||
it("keeps a Podman runtime and ignores the default or broken config", () => {
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: '{"runtime":"podman"}',
|
||||
}),
|
||||
).toEqual({ enableDocker: true, containerRuntime: "podman" });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: '{"runtime":"docker"}',
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
expect(
|
||||
dockerSettingsFromRow({
|
||||
id: 1,
|
||||
enable_docker: 1,
|
||||
docker_config: "{oops",
|
||||
}),
|
||||
).toEqual({ enableDocker: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("runDockerSettingsMigration", () => {
|
||||
it("moves every host's docker options and skips hosts with nothing set", async () => {
|
||||
state.hostRows = [
|
||||
{ id: 1, enable_docker: 1, docker_config: null },
|
||||
{ id: 2, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
|
||||
{ id: 3, enable_docker: 0, docker_config: null },
|
||||
];
|
||||
|
||||
const result = await runDockerSettingsMigration();
|
||||
|
||||
expect(result).toEqual({ hostsMoved: 2, hostsSkipped: 0 });
|
||||
expect(hostValues(1)).toEqual({ enableDocker: true });
|
||||
expect(hostValues(2)).toEqual({
|
||||
enableDocker: true,
|
||||
containerRuntime: "podman",
|
||||
});
|
||||
expect(hostValues(3)).toEqual({});
|
||||
});
|
||||
|
||||
it("changes nothing when run twice", async () => {
|
||||
state.hostRows = [
|
||||
{ id: 1, enable_docker: 1, docker_config: '{"runtime":"podman"}' },
|
||||
];
|
||||
await runDockerSettingsMigration();
|
||||
const before = JSON.stringify(state.pluginRows);
|
||||
|
||||
const second = await runDockerSettingsMigration();
|
||||
|
||||
expect(second).toEqual({ hostsMoved: 0, hostsSkipped: 1 });
|
||||
expect(JSON.stringify(state.pluginRows)).toBe(before);
|
||||
});
|
||||
|
||||
it("keeps a value already saved in the plugin", async () => {
|
||||
state.pluginRows.push({
|
||||
pluginId: "docker",
|
||||
scope: "host",
|
||||
scopeId: "1",
|
||||
key: "enableDocker",
|
||||
value: "false",
|
||||
});
|
||||
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
|
||||
|
||||
await runDockerSettingsMigration();
|
||||
|
||||
expect(hostValues(1)).toEqual({ enableDocker: false });
|
||||
});
|
||||
|
||||
it("does nothing before the plugin row exists or once the columns are gone", async () => {
|
||||
state.hostRows = [{ id: 1, enable_docker: 1, docker_config: null }];
|
||||
state.pluginInstalled = false;
|
||||
expect(await runDockerSettingsMigration()).toEqual({
|
||||
hostsMoved: 0,
|
||||
hostsSkipped: 0,
|
||||
});
|
||||
|
||||
state.pluginInstalled = true;
|
||||
state.columnsGone = true;
|
||||
expect(await runDockerSettingsMigration()).toEqual({
|
||||
hostsMoved: 0,
|
||||
hostsSkipped: 0,
|
||||
});
|
||||
expect(state.pluginRows).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user