98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
|
|
import { assertEquals } from 'jsr:@std/assert';
|
||
|
|
|
||
|
|
const shouldRunDockerSmoke = Deno.env.get('OBJST_RUN_DOCKER_SMOKE') === '1';
|
||
|
|
|
||
|
|
interface ICommandResult {
|
||
|
|
code: number;
|
||
|
|
stdout: string;
|
||
|
|
stderr: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function runCommand(
|
||
|
|
command: string[],
|
||
|
|
options: { cwd?: string; check?: boolean } = {},
|
||
|
|
): Promise<ICommandResult> {
|
||
|
|
const output = await new Deno.Command(command[0], {
|
||
|
|
args: command.slice(1),
|
||
|
|
cwd: options.cwd,
|
||
|
|
stdout: 'piped',
|
||
|
|
stderr: 'piped',
|
||
|
|
}).output();
|
||
|
|
|
||
|
|
const result = {
|
||
|
|
code: output.code,
|
||
|
|
stdout: new TextDecoder().decode(output.stdout).trim(),
|
||
|
|
stderr: new TextDecoder().decode(output.stderr).trim(),
|
||
|
|
};
|
||
|
|
|
||
|
|
if (options.check !== false && result.code !== 0) {
|
||
|
|
throw new Error(`Command failed: ${command.join(' ')}\n${result.stderr}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function waitForOk(url: string, timeoutMs: number): Promise<void> {
|
||
|
|
const deadline = Date.now() + timeoutMs;
|
||
|
|
|
||
|
|
while (Date.now() < deadline) {
|
||
|
|
try {
|
||
|
|
const response = await fetch(url);
|
||
|
|
if (response.ok) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
// Container may still be starting.
|
||
|
|
}
|
||
|
|
|
||
|
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||
|
|
}
|
||
|
|
|
||
|
|
throw new Error(`Timed out waiting for ${url}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
Deno.test({
|
||
|
|
name: 'Docker image builds and serves the management UI',
|
||
|
|
ignore: !shouldRunDockerSmoke,
|
||
|
|
sanitizeOps: false,
|
||
|
|
sanitizeResources: false,
|
||
|
|
fn: async () => {
|
||
|
|
await runCommand(['docker', '--version']);
|
||
|
|
|
||
|
|
const imageTag = `objectstorage-smoke:${crypto.randomUUID().slice(0, 8)}`;
|
||
|
|
const containerName = `objectstorage-smoke-${crypto.randomUUID().slice(0, 8)}`;
|
||
|
|
const storagePort = 19190;
|
||
|
|
const uiPort = 19191;
|
||
|
|
|
||
|
|
try {
|
||
|
|
await runCommand(['docker', 'build', '-t', imageTag, '.']);
|
||
|
|
|
||
|
|
const runResult = await runCommand([
|
||
|
|
'docker',
|
||
|
|
'run',
|
||
|
|
'-d',
|
||
|
|
'--name',
|
||
|
|
containerName,
|
||
|
|
'-p',
|
||
|
|
`${storagePort}:9000`,
|
||
|
|
'-p',
|
||
|
|
`${uiPort}:3000`,
|
||
|
|
'-e',
|
||
|
|
'OBJST_ADMIN_PASSWORD=docker-smoke-admin',
|
||
|
|
'-e',
|
||
|
|
'OBJST_ACCESS_KEY=docker-smoke-key',
|
||
|
|
'-e',
|
||
|
|
'OBJST_SECRET_KEY=docker-smoke-secret',
|
||
|
|
imageTag,
|
||
|
|
]);
|
||
|
|
|
||
|
|
assertEquals(runResult.stdout.length > 0, true);
|
||
|
|
await waitForOk(`http://127.0.0.1:${uiPort}/readyz`, 30000);
|
||
|
|
await waitForOk(`http://127.0.0.1:${storagePort}/-/ready`, 30000);
|
||
|
|
} finally {
|
||
|
|
await runCommand(['docker', 'rm', '-f', containerName], { check: false });
|
||
|
|
await runCommand(['docker', 'rmi', '-f', imageTag], { check: false });
|
||
|
|
}
|
||
|
|
},
|
||
|
|
});
|