source: Klonkt/scripts/instance-env.mjs@ a4fea5e

main
Last change on this file since a4fea5e was a4fea5e, checked in by roboburr <roboburr@…>, 5 weeks ago

De instance-naam is niet de site-slug, en vlagwaarden zijn geen argumenten

Vervolg op 6248497. Het instance-pad werkte, maar export-archive.mjs liz gaf
"onbekende site: liz" -- en liet je vervolgens raden.

## De naam van de instance is niet de slug van de site

De map onder de data-root en de systemd-unit heten liz; de SITE in die database
kan een andere slug hebben. Ze vallen vaak samen en soms niet, en dan stond je met
een foutmelding die niets prijsgaf.

Twee dingen veranderd:

  • de foutmelding zegt nu WAT er wel in die database staat, en als er helemaal geen sites in staan vraagt hij of DATABASE_PATH wel klopt
  • de site-slug is optioneel geworden. Staat er precies een site, dan is de keuze niet dubbelzinnig en hoef je hem niet te weten; hij meldt welke hij nam. Bij meerdere sites stopt hij en noemt ze.

node scripts/export-archive.mjs <instance> [site-slug]

## En een parseerfout die ik er zelf net in had gezet

args.filter(a => !a.startsWith('-')) pikt de WAARDE van een vlag op als
positioneel argument. Met liz --data-root /var/lib/klonkt werd /var/lib/klonkt
de site-slug. Gevonden bij het testen van het bovenstaande, en import-archive.mjs
had hem ook: daar zou het pad naar het archief verschoven zijn.

Nu een gedeelde splitsArgs() die weet welke vlaggen een waarde slikken.

Getoetst met een instance 'liz' waarvan de site 'lizzy' heet -- precies het geval
dat op productie omviel: zonder slug pakt hij lizzy en zegt dat, met de verkeerde
slug noemt hij wat er wel is, en met de juiste plus --out schrijft hij het archief.
Suite 577/577 onder UTC en Europe/Amsterdam.

  • Property mode set to 100644
File size: 4.8 KB
Line 
1//
2// Welke instance bedoel je?
3//
4// Op een split install (deploy/MULTI-INSTANCE.md) deelt elke Klonkt dezelfde code
5// in /opt/klonkt, maar staat zijn DATA onder /var/lib/klonkt/<slug>/ met een eigen
6// .env. Een script dat vanuit de code-map draait zonder die .env te lezen opent
7// dus de VERKEERDE database -- en op een machine die ooit de oude enkelvoudige
8// opzet draaide is dat een achtergebleven storage/database.sqlite in de checkout.
9//
10// Dat ging in de praktijk mis en op de ergste manier: het meldde SUCCES. Een
11// export van een site met zeven jaar aan posten schreef een archief van 444 bytes
12// met "posts: 0", omdat hij in een oude lege database keek. Een leeg archief dat
13// zegt dat het gelukt is, is erger dan een foutmelding.
14//
15// Vandaar dit: los, want de importer en het herstel hebben hem net zo hard nodig.
16
17import fs from 'fs';
18import path from 'path';
19
20/** Lees een .env zonder afhankelijkheden. Alleen KEY=value, # is commentaar. */
21export function leesEnv(pad) {
22 const uit = {};
23 for (const regel of fs.readFileSync(pad, 'utf8').split('\n')) {
24 const s = regel.trim();
25 if (!s || s.startsWith('#')) continue;
26 const i = s.indexOf('=');
27 if (i < 1) continue;
28 let v = s.slice(i + 1).trim();
29 if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1);
30 uit[s.slice(0, i).trim()] = v;
31 }
32 return uit;
33}
34
35/**
36 * Zet de omgeving voor EEN instance, en zeg hardop welke.
37 *
38 * Moet AANGEROEPEN WORDEN VOORDAT src/config/database.js geladen wordt: die leest
39 * DATABASE_PATH bij import en opent de database meteen. Vandaar dat de scripts
40 * hun service-import uitstellen tot na deze aanroep.
41 *
42 * @returns {{bron: string, env: object}} waar de instellingen vandaan kwamen
43 */
44export function kiesInstance(slug, opts = {}) {
45 const dataRoot = opts.dataRoot || process.env.KLONKT_DATA_ROOT || '/var/lib/klonkt';
46 const kandidaat = opts.envPad || path.join(dataRoot, slug, '.env');
47
48 if (fs.existsSync(kandidaat)) {
49 const env = leesEnv(kandidaat);
50 // De data-map van de instance is de wortel voor relatieve paden in zijn .env,
51 // precies zoals de unit hem draait (WorkingDirectory is de code, DATA_DIR de data).
52 const basis = env.DATA_DIR || path.dirname(kandidaat);
53 const absoluut = (p) => (p && !path.isAbsolute(p) ? path.resolve(basis, p) : p);
54 for (const k of ['DATABASE_PATH', 'MEDIA_PATH', 'AUDIO_PATH', 'AVATAR_PATH', 'COVER_PATH']) {
55 if (env[k]) process.env[k] = absoluut(env[k]);
56 }
57 if (env.PUBLIC_BASE_URL) process.env.PUBLIC_BASE_URL = env.PUBLIC_BASE_URL;
58 if (env.DATA_DIR) process.env.DATA_DIR = env.DATA_DIR;
59 return { bron: kandidaat, env };
60 }
61
62 if (opts.envPad) {
63 // Expliciet meegegeven en niet gevonden: dat is een vergissing en geen reden
64 // om stilletjes iets anders te openen.
65 throw new Error(`geen .env op ${opts.envPad}`);
66 }
67 return { bron: null, env: {} };
68}
69
70/**
71 * Weiger te beginnen als we niet kunnen weten wiens gegevens dit zijn.
72 *
73 * Zonder PUBLIC_BASE_URL komt er een archief uit met een lege `origin`, en dan
74 * weigert de importer de AP-ids te behouden -- hij maakt nieuwe. Daarmee valt
75 * precies de belofte weg waar het formaat om draait: een herstel waarna de
76 * boosts en antwoorden elders hun post terugvinden. Dat mag geen voetnoot in de
77 * uitvoer zijn.
78 */
79export function eisOrigin(bron) {
80 if (process.env.PUBLIC_BASE_URL) return;
81 console.error([
82 'GESTOPT: er is geen PUBLIC_BASE_URL.',
83 '',
84 'Zonder die waarde krijgt het archief een lege origin, en dan maakt een import',
85 'NIEUWE ActivityPub-ids in plaats van de oude te behouden. Boosts, likes en',
86 'antwoorden elders vinden hun post dan niet meer terug -- het archief is dan',
87 'een kopie van de tekst en geen herstel.',
88 '',
89 bron
90 ? `Gelezen uit ${bron}, maar PUBLIC_BASE_URL staat daar niet in.`
91 : 'Geen .env van een instance gevonden. Op een split install:\n'
92 + ' node scripts/export-archive.mjs <slug> --data-root /var/lib/klonkt',
93 ].join('\n'));
94 process.exit(1);
95}
96
97/**
98 * Argumenten splitsen in vrije woorden en vlaggen.
99 *
100 * Nodig omdat de naieve versie -- alles wat niet met een streepje begint is
101 * positioneel -- de WAARDE van een vlag als positioneel argument oppikt. Met
102 * `export-archive.mjs liz --data-root /var/lib/klonkt` werd /var/lib/klonkt de
103 * site-slug. Precies zo'n fout die pas opvalt als iemand hem gebruikt.
104 *
105 * @param {string[]} args
106 * @param {string[]} metWaarde vlaggen die een waarde slikken
107 */
108export function splitsArgs(args, metWaarde) {
109 const vrij = [];
110 const vlaggen = {};
111 for (let i = 0; i < args.length; i += 1) {
112 const a = args[i];
113 if (!a.startsWith('-')) { vrij.push(a); continue; }
114 if (metWaarde.includes(a)) { vlaggen[a] = args[i + 1] ?? null; i += 1; continue; }
115 vlaggen[a] = true;
116 }
117 return { vrij, vlaggen };
118}
Note: See TracBrowser for help on using the repository browser.