Files
headplane/tests/integration/setup/start-headscale.ts
T
2026-03-19 12:35:25 -04:00

55 lines
1.4 KiB
TypeScript

import { join } from "node:path";
import { fileURLToPath } from "node:url";
import tc from "testcontainers";
export interface HeadscaleEnv {
container: tc.StartedTestContainer;
apiUrl: string;
apiKey: string;
}
export interface HeadscaleOptions {
labels?: Record<string, string>;
}
const cwd = fileURLToPath(import.meta.url);
const config = join(cwd, "..", "config.yaml");
export async function startHeadscale(
version: string,
options?: HeadscaleOptions,
): Promise<HeadscaleEnv> {
let builder = new tc.GenericContainer(`headscale/headscale:${version}`)
.withExposedPorts(8080)
.withWaitStrategy(
tc.Wait.forHttp("/health", 8080).withStartupTimeout(30_000).forStatusCode(200),
)
.withCopyFilesToContainer([
{
source: config,
target: "/etc/headscale/config.yaml",
},
])
.withCommand(["serve"]);
if (options?.labels) {
builder = builder.withLabels(options.labels);
}
const container = await builder.start();
const host = container.getHost();
const port = container.getMappedPort(8080);
const apiUrl = `http://${host}:${port}`;
const exec = await container.exec(["headscale", "apikeys", "create", "-o", "json"]);
if (exec.exitCode !== 0) {
throw new Error(`headscale apikeys create failed:\n${exec.stderr}`);
}
const apiKey = JSON.parse(exec.stdout.toString());
return { container, apiUrl, apiKey };
}