bazarr: reach sonarr and radarr through the mesh; placed dirs; the image ace runs
bazarr reached sonarr and radarr as `sonarr:8989` and `radarr:7878`, container names on HAL's shared network, which the mesh does not have. It now requires sonarr-api and radarr-api (provided since #156) and a run-once step writes host, port, TLS, base path and key into bazarr through bazarr's own POST /api/system/settings - the call its settings screen makes - only for the fields that differ, and reads them back. bazarr's config.yaml is not written by the mesh: bazarr holds it in memory and rewrites it, so the two would overwrite each other. The key is tried against the app first; a refused key (a minted pair credential before the operator accepts the app's own) is never written, and the step fails naming the `secret accept` that fixes it. Declared last so its failing gates nothing else (ADR 0136); restart-on its four inputs. The api-key own-secret is gone. bazarr makes its own key and nothing lets the mesh set it, so a minted one could never work; the tools and the step read auth.apikey from bazarr's own config/config.yaml (mounted read-only), which also stays right if the key is regenerated. Nothing to accept. The config dir is a pathless ${dir:config}; config.json and the bindings live in a placed state dir; /var/lib/mesh/bazarr keeps only the broker. The image is pinned to the digest ace runs (v1.6.1-ls364); the old pin was v1.6.0-ls361, older than ace's database. Based on feat/servarr-api-provision (#156); this branch contains it. Verified: catalogue tests with MESH_CATALOGUE pass (not skipped); a resolve of sonarr+radarr+bazarr on a fake ace renders both bindings and sealed credentials into the state dir with every ${} filled, and bazarr alone is refused naming sonarr and radarr; strict tsc passes and the Dockerfile's non-strict compile builds; 8 node tests pass; the compiled step against the pinned image in a throwaway container with fake sonarr/radarr wrote sonarr (ip, port, apikey), refused radarr's minted key and wrote nothing for it, wrote radarr once the key was right, and changed nothing on a third run - the values landed in config.yaml.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// bazarr's own API key, found where bazarr keeps it. Shared by the client (tools, events) and the
|
||||
// Servarr step, and kept apart from client.ts so the step and its test load it without the client.
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
/**
|
||||
* bazarr's own API key, read from where bazarr keeps it: `auth.apikey` in `config/config.yaml` under
|
||||
* its config directory. bazarr makes this key itself on first start and nothing lets the mesh set it,
|
||||
* so a key the mesh minted could never work; reading bazarr's own file needs nothing accepted and
|
||||
* stays right if the operator regenerates the key in bazarr's settings screen. The file is read, never
|
||||
* written. Undefined when the file or the key is not there.
|
||||
*/
|
||||
export function apiKeyFromConfigDir(configDir?: string): string | undefined {
|
||||
if (!configDir) return undefined;
|
||||
let text: string;
|
||||
try { text = readFileSync(`${configDir.replace(/\/$/, "")}/config/config.yaml`, "utf8"); }
|
||||
catch { return undefined; }
|
||||
return apiKeyFromConfigYaml(text);
|
||||
}
|
||||
|
||||
/** `auth.apikey` from the text of bazarr's config.yaml — a top-level `auth:` mapping, one level deep. */
|
||||
export function apiKeyFromConfigYaml(text: string): string | undefined {
|
||||
let inAuth = false;
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
if (/^\S/.test(line)) {
|
||||
inAuth = /^auth:\s*$/.test(line);
|
||||
continue;
|
||||
}
|
||||
if (!inAuth) continue;
|
||||
const m = line.match(/^\s+apikey:\s*(.*?)\s*$/);
|
||||
if (m) {
|
||||
const v = m[1].replace(/^(['"])(.*)\1$/, "$2").trim();
|
||||
return v || undefined;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user