add Anope->Echo migration importer (echo import)
All checks were successful
CI / check (push) Successful in 3m41s
All checks were successful
CI / check (push) Successful in 3m41s
New 'echo import <anope.json> <out.log> [node]' subcommand builds a fresh event log from an Anope db_json: accounts (identity only — Anope's one-way password hashes can't become SCRAM verifiers, so migrated users auth by certfp/external authority), grouped nicks, cert fingerprints, vhosts, channels (+desc/topic/ assigned bot), access mapped to op/voice by each channel's AUTOOP/AUTOVOICE thresholds, param-less mode locks, BotServ bots (service pseudo-clients skipped), and memos. Read-only on the source; self-verifies by replaying the produced log. Verified against the live backup (11 accounts, 10 channels, 10 bots) + a unit test over a synthetic fixture. The prerequisite for a safe cutover.
This commit is contained in:
parent
b23bf5d8a9
commit
062eae703e
3 changed files with 366 additions and 0 deletions
25
src/main.rs
25
src/main.rs
|
|
@ -7,6 +7,7 @@ mod gossip;
|
|||
mod grpc;
|
||||
mod jsonrpc;
|
||||
mod link;
|
||||
mod migrate;
|
||||
mod proto;
|
||||
|
||||
use anyhow::Result;
|
||||
|
|
@ -40,6 +41,30 @@ async fn main() -> Result<()> {
|
|||
)
|
||||
.init();
|
||||
|
||||
// One-off migration: `echo import <anope.json> <out.log> [node-name]` builds a
|
||||
// fresh event log from an Anope db_json and exits, touching nothing else.
|
||||
let argv: Vec<String> = std::env::args().collect();
|
||||
if argv.get(1).map(String::as_str) == Some("import") {
|
||||
let (Some(src), Some(out)) = (argv.get(2), argv.get(3)) else {
|
||||
eprintln!("usage: echo import <anope.json> <out.log> [node-name]");
|
||||
std::process::exit(2);
|
||||
};
|
||||
let node = argv.get(4).map(String::as_str).unwrap_or("services");
|
||||
let s = migrate::import_anope(src, out, node)?;
|
||||
println!(
|
||||
"imported: {} accounts, {} grouped nicks, {} certs, {} vhosts, {} channels, {} access, {} mlocked, {} bots, {} memos",
|
||||
s.accounts, s.grouped_nicks, s.certs, s.vhosts, s.channels, s.access, s.mlocked, s.bots, s.memos
|
||||
);
|
||||
for note in &s.skipped {
|
||||
println!(" skipped: {note}");
|
||||
}
|
||||
println!(
|
||||
"verified (log replays to): {} accounts, {} channels, {} bots",
|
||||
s.loaded_accounts, s.loaded_channels, s.loaded_bots
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let path = std::env::args().nth(1).unwrap_or_else(|| "config.toml".to_string());
|
||||
let cfg = config::Config::load(&path)?;
|
||||
let ts = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue