mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 22:25: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,105 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import type {
|
||||
DockerEvent,
|
||||
DockerEventsV1,
|
||||
DockerServiceV1,
|
||||
} from "../../src/backend/index.js";
|
||||
import { startServer, type TestServer } from "./server";
|
||||
|
||||
let server: TestServer | null = null;
|
||||
|
||||
afterEach(async () => {
|
||||
vi.useRealTimers();
|
||||
await server?.close();
|
||||
server = null;
|
||||
});
|
||||
|
||||
const psState = (state: string, status = "Up") =>
|
||||
`{"name":"web","state":"${state}","status":"${status}"}\n`;
|
||||
|
||||
describe("docker.containers service", () => {
|
||||
it("lists containers and runs actions as the caller", async () => {
|
||||
server = await startServer();
|
||||
const docker = server.mock.services.get(
|
||||
"docker.containers",
|
||||
) as DockerServiceV1;
|
||||
|
||||
const containers = await server.mock.ctx.asUser("user-1", () =>
|
||||
docker.listContainers(7),
|
||||
);
|
||||
expect(containers).toEqual([
|
||||
expect.objectContaining({ id: "abc123", name: "web" }),
|
||||
]);
|
||||
|
||||
await server.mock.ctx.asUser("user-1", () =>
|
||||
docker.action(7, "web", "restart"),
|
||||
);
|
||||
expect(server.client.commands.at(-1)).toMatch(/ docker restart web$/);
|
||||
expect(server.mock.sshConnections.at(-1)).toMatchObject({
|
||||
host: 7,
|
||||
pool: "docker",
|
||||
});
|
||||
|
||||
await expect(
|
||||
server.mock.ctx.asUser("user-1", () =>
|
||||
docker.action(7, "web; rm -rf /", "stop"),
|
||||
),
|
||||
).rejects.toThrow(/Invalid container name/);
|
||||
});
|
||||
|
||||
it("needs a calling user", async () => {
|
||||
server = await startServer();
|
||||
const docker = server.mock.services.get(
|
||||
"docker.containers",
|
||||
) as DockerServiceV1;
|
||||
await expect(docker.listContainers(7)).rejects.toThrow(/calling user/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("docker.events service", () => {
|
||||
it("reports state changes between polls to every subscriber", async () => {
|
||||
vi.useFakeTimers({ toFake: ["Date"] });
|
||||
server = await startServer();
|
||||
const events = server.mock.services.get("docker.events") as DockerEventsV1;
|
||||
const seen: DockerEvent[] = [];
|
||||
const listener = (event: DockerEvent) => seen.push(event);
|
||||
|
||||
const unsubscribe = await server.mock.ctx.asUser("user-1", () =>
|
||||
events.subscribe(7, listener),
|
||||
);
|
||||
// Subscribing the same listener again is a no-op.
|
||||
await server.mock.ctx.asUser("user-1", () => events.subscribe(7, listener));
|
||||
|
||||
const poll = async (output: string) => {
|
||||
server!.client.reply(/ ps -a --format/, { stdout: output });
|
||||
vi.setSystemTime(Date.now() + 61_000);
|
||||
await server!.mock.runScheduled();
|
||||
};
|
||||
|
||||
await poll(psState("running"));
|
||||
expect(seen).toEqual([]);
|
||||
|
||||
await poll(psState("exited", "Exited (1)"));
|
||||
expect(seen).toEqual([{ hostId: 7, container: "web", event: "exited" }]);
|
||||
|
||||
await poll(psState("running", "Up 1 second (unhealthy)"));
|
||||
expect(seen.slice(1)).toEqual([
|
||||
{ hostId: 7, container: "web", event: "started" },
|
||||
{ hostId: 7, container: "web", event: "unhealthy" },
|
||||
]);
|
||||
|
||||
unsubscribe();
|
||||
const before = server.client.commands.length;
|
||||
await poll(psState("exited"));
|
||||
expect(server.client.commands.length).toBe(before);
|
||||
expect(seen).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("stops polling once the plugin is disposed", async () => {
|
||||
server = await startServer();
|
||||
const events = server.mock.services.get("docker.events") as DockerEventsV1;
|
||||
await server.mock.ctx.asUser("user-1", () => events.subscribe(7, () => {}));
|
||||
for (const dispose of [...server.mock.disposals].reverse()) await dispose();
|
||||
expect(server.mock.scheduled.every((job) => job.stopped)).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user