feat(image): add scratch container image
Two-stage build producing a static /app on scratch; e2e tests for image contents, server and CLI through docker exec, socket handling, lifecycle and host/image parity.
This commit is contained in:
1 parent
0a6023e942
commit
581a672fcf
9 files changed
+1858
No files matched your search
@@ -0,0 +1,64 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// Copyright (C) 2026 Bryan Joshua Pedini
|
||||
|
||||
/**
|
||||
* Self-check of the image helpers used by the container-image suite (phase 2 adds the real
|
||||
* image tests next to this file). Proves: start with socket + data mounts and a published port,
|
||||
* HTTP readiness, `docker exec` CLI results, curl from outside, DB snapshot of root-owned files,
|
||||
* graceful stop exit code, one-shot `docker run`, and cleanup.
|
||||
*/
|
||||
import {
|
||||
test,
|
||||
expect,
|
||||
assertDbInvariants,
|
||||
expectCliSuccess,
|
||||
expectContainersResponse,
|
||||
parseLogs,
|
||||
parseTokenList,
|
||||
readOperations,
|
||||
readTokens,
|
||||
} from '../../harness';
|
||||
|
||||
test('image helpers: start, exec, HTTP, snapshot, stop, one-shot run', async ({ image, http }) => {
|
||||
test.setTimeout(120_000);
|
||||
const c = await image.start({ logLevel: 'INFO' });
|
||||
expect(c.name).toMatch(/^dpsapi-e2e-[0-9a-f]{8}-[0-9a-f]{8}-img\d+$/);
|
||||
c.fakeDocker!.many(2);
|
||||
|
||||
const created = await c.exec(['token', 'new', 'image selfcheck']);
|
||||
expectCliSuccess(created, { stderr: '' });
|
||||
const token = created.stdout.trim();
|
||||
const listed = await c.exec(['token', 'list']);
|
||||
expectCliSuccess(listed, { stderr: '' });
|
||||
expect(parseTokenList(listed.stdout).map((r) => [r.token, r.description])).toEqual([[token, 'image selfcheck']]);
|
||||
|
||||
expect(expectContainersResponse(await http.get(c.url(), { token }))).toHaveLength(2);
|
||||
expect(expectContainersResponse(await http.curl({ url: c.url(), token }))).toHaveLength(2);
|
||||
|
||||
const snap = await c.snapshotDb();
|
||||
expect(readTokens(snap).map((t) => t.token)).toEqual([token]);
|
||||
expect(readOperations(snap)).toHaveLength(2);
|
||||
assertDbInvariants(snap, { tokenCount: 1, operationCount: 2 });
|
||||
|
||||
const exit = await c.stop();
|
||||
expect(exit.exitCode).toBe(0);
|
||||
const logs = parseLogs(exit.stderr);
|
||||
expect(logs.requests()).toHaveLength(2);
|
||||
expect(logs.has({ msg: 'server stopped' })).toBe(true);
|
||||
|
||||
// one-shot container on the same data directory
|
||||
const again = await image.run(['token', 'list'], { dataDir: c.dataDir });
|
||||
expectCliSuccess(again);
|
||||
expect(parseTokenList(again.stdout)).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('image helpers: the image binary extracted to the host runs through the host CLI/server helpers', async ({ image, cli, startServer, http, ws }) => {
|
||||
const bin = await image.extractBinary();
|
||||
const imageCli = cli.withBinary(bin);
|
||||
const token = await imageCli.tokenNew('from extracted binary');
|
||||
const server = await startServer({ binary: bin });
|
||||
expectContainersResponse(await http.get(server.url(), { token }));
|
||||
expect((await server.stop()).exitCode).toBe(0);
|
||||
expect((await imageCli.tokenList()).map((r) => r.token)).toEqual([token]);
|
||||
assertDbInvariants(ws.dbPath, { tokenCount: 1, operationCount: 1 });
|
||||
});
|
||||
Reference in new issue
Block a user