headplane/app/server/config/schema.ts
Georgios Ntoutsos 5b3b4eb240 Add filtering by container labels
This commit adds the ability to filter containers by their labels in the
Docker integration. The new functionality allows users to specify
container labels in the configuration, instead of container names, to
allow for dynamic container name resolution.
This is particularly useful in environments where container names may
change frequently or are not defined in advance.

Fixes #193

Signed-off-by: Georgios Ntoutsos <gntouts@nubificus.co.uk>
2025-04-24 17:07:50 +03:00

96 lines
2.6 KiB
TypeScript

import { type } from 'arktype';
const stringToBool = type('string | boolean').pipe((v) => Boolean(v));
const serverConfig = type({
host: 'string.ip',
port: type('string | number.integer').pipe((v) => Number(v)),
cookie_secret: '32 <= string <= 32',
cookie_secure: stringToBool,
agent: type({
authkey: 'string = ""',
ttl: 'number.integer = 180000', // Default to 3 minutes
cache_path: 'string = "/var/lib/headplane/agent_cache.json"',
})
.onDeepUndeclaredKey('reject')
.default(() => ({
authkey: '',
ttl: 180000,
cache_path: '/var/lib/headplane/agent_cache.json',
})),
});
const oidcConfig = type({
issuer: 'string.url',
client_id: 'string',
client_secret: 'string?',
client_secret_path: 'string?',
token_endpoint_auth_method:
'"client_secret_basic" | "client_secret_post" | "client_secret_jwt"',
redirect_uri: 'string.url?',
user_storage_file: 'string = "/var/lib/headplane/users.json"',
disable_api_key_login: stringToBool,
headscale_api_key: 'string',
strict_validation: stringToBool.default(true),
}).onDeepUndeclaredKey('reject');
const headscaleConfig = type({
url: type('string.url').pipe((v) => (v.endsWith('/') ? v.slice(0, -1) : v)),
tls_cert_path: 'string?',
public_url: 'string.url?',
config_path: 'string?',
config_strict: stringToBool,
}).onDeepUndeclaredKey('reject');
const containerLabel = type({
name: 'string',
value: 'string',
}).optional();
const dockerConfig = type({
enabled: stringToBool,
container_name: 'string',
socket: 'string = "unix:///var/run/docker.sock"',
container_label: containerLabel,
});
const kubernetesConfig = type({
enabled: stringToBool,
pod_name: 'string',
validate_manifest: stringToBool,
});
const procConfig = type({
enabled: stringToBool,
});
const integrationConfig = type({
'docker?': dockerConfig,
'kubernetes?': kubernetesConfig,
'proc?': procConfig,
}).onDeepUndeclaredKey('reject');
const partialIntegrationConfig = type({
'docker?': dockerConfig.partial(),
'kubernetes?': kubernetesConfig.partial(),
'proc?': procConfig.partial(),
}).partial();
export const headplaneConfig = type({
debug: stringToBool,
server: serverConfig,
'oidc?': oidcConfig,
'integration?': integrationConfig,
headscale: headscaleConfig,
}).onDeepUndeclaredKey('delete');
export const partialHeadplaneConfig = type({
debug: stringToBool,
server: serverConfig.partial(),
'oidc?': oidcConfig.partial(),
'integration?': partialIntegrationConfig,
headscale: headscaleConfig.partial(),
}).partial();
export type HeadplaneConfig = typeof headplaneConfig.infer;
export type PartialHeadplaneConfig = typeof partialHeadplaneConfig.infer;