feat: add uptime runner agent
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import type { IUptimeRunnerConfig } from './interfaces.ts';
|
||||
|
||||
export const DEFAULT_CONFIG_PATH = '/etc/uptimerunner/config.json';
|
||||
|
||||
export async function loadConfig(configPathArg = getConfigPath()): Promise<IUptimeRunnerConfig> {
|
||||
const fileConfig = await readConfigFile(configPathArg);
|
||||
const config = applyEnvironmentOverrides(fileConfig);
|
||||
validateConfig(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
export async function writeConfig(
|
||||
configArg: IUptimeRunnerConfig,
|
||||
configPathArg = getConfigPath(),
|
||||
): Promise<void> {
|
||||
validateConfig(configArg);
|
||||
const configDir = configPathArg.slice(0, configPathArg.lastIndexOf('/')) || '.';
|
||||
await Deno.mkdir(configDir, { recursive: true });
|
||||
await Deno.writeTextFile(`${configPathArg}.tmp`, `${JSON.stringify(configArg, null, 2)}\n`);
|
||||
await Deno.rename(`${configPathArg}.tmp`, configPathArg);
|
||||
}
|
||||
|
||||
export function getConfigPath(): string {
|
||||
return Deno.env.get('UPTIMERUNNER_CONFIG') || DEFAULT_CONFIG_PATH;
|
||||
}
|
||||
|
||||
export function applyEnvironmentOverrides(configArg: Partial<IUptimeRunnerConfig>) {
|
||||
const labels = Deno.env.get('UPTIMERUNNER_LABELS');
|
||||
const pollIntervalMs = Deno.env.get('UPTIMERUNNER_POLL_INTERVAL_MS');
|
||||
const maxConcurrentChecks = Deno.env.get('UPTIMERUNNER_MAX_CONCURRENT_CHECKS');
|
||||
|
||||
return {
|
||||
...configArg,
|
||||
instanceUrl: Deno.env.get('UPTIMERUNNER_INSTANCE_URL') || configArg.instanceUrl,
|
||||
runnerId: Deno.env.get('UPTIMERUNNER_RUNNER_ID') || configArg.runnerId,
|
||||
token: Deno.env.get('UPTIMERUNNER_TOKEN') || configArg.token,
|
||||
labels: labels
|
||||
? labels.split(',').map((labelArg) => labelArg.trim()).filter(Boolean)
|
||||
: configArg.labels,
|
||||
pollIntervalMs: pollIntervalMs ? Number(pollIntervalMs) : configArg.pollIntervalMs,
|
||||
maxConcurrentChecks: maxConcurrentChecks
|
||||
? Number(maxConcurrentChecks)
|
||||
: configArg.maxConcurrentChecks,
|
||||
} satisfies Partial<IUptimeRunnerConfig>;
|
||||
}
|
||||
|
||||
export function validateConfig(
|
||||
configArg: Partial<IUptimeRunnerConfig>,
|
||||
): asserts configArg is IUptimeRunnerConfig {
|
||||
if (!configArg.instanceUrl) {
|
||||
throw new Error('Missing instanceUrl. Set it in config or UPTIMERUNNER_INSTANCE_URL.');
|
||||
}
|
||||
if (!configArg.runnerId) {
|
||||
throw new Error('Missing runnerId. Set it in config or UPTIMERUNNER_RUNNER_ID.');
|
||||
}
|
||||
if (!configArg.token) {
|
||||
throw new Error('Missing token. Set it in config or UPTIMERUNNER_TOKEN.');
|
||||
}
|
||||
if (configArg.pollIntervalMs !== undefined && configArg.pollIntervalMs < 1000) {
|
||||
throw new Error('pollIntervalMs must be at least 1000ms.');
|
||||
}
|
||||
if (configArg.maxConcurrentChecks !== undefined && configArg.maxConcurrentChecks < 1) {
|
||||
throw new Error('maxConcurrentChecks must be at least 1.');
|
||||
}
|
||||
}
|
||||
|
||||
async function readConfigFile(configPathArg: string): Promise<Partial<IUptimeRunnerConfig>> {
|
||||
try {
|
||||
const configText = await Deno.readTextFile(configPathArg);
|
||||
return JSON.parse(configText) as Partial<IUptimeRunnerConfig>;
|
||||
} catch (error) {
|
||||
if (error instanceof Deno.errors.NotFound) {
|
||||
return {};
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user