feat(sidecar): make the sidecar installable — CLI, --print-config, anchored data paths
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 7m52s
All checks were successful
PR Checks / rust-gates (pull_request) Successful in 7m52s
Phase 0.2 of the installer plan (docs/installer/PLAN.md §5). The installer has to drive this binary non-interactively, and today it cannot: the auth token is only readable by scraping the startup log, the config path can only be named through an environment variable, and a relative db path follows the process working directory — which a service manager, not the operator, chooses. - Add a four-flag CLI (cli.rs): --print-config, --config <PATH>, --version, --help. Hand-rolled; an argument-parsing dependency would be larger than the code it replaced. An unrecognized flag exits 2 rather than starting a sidecar that is not the one that was asked for. - --print-config resolves the configuration exactly as a normal start does — including writing a missing config file and generating a blank auth token — and prints it as JSON on stdout: versions, protocol, both bind addresses, ws path, resolved db path, and the token. config_created / token_generated let a re-run tell "read an existing install" from "provisioned a new one". The log subscriber is deliberately not started in this mode, so the document is the whole output. - Anchor a relative [store].path to the config file's directory instead of the CWD, and report resolved absolute paths. A unit pinning UOLINK_CONFIG now keeps its database beside its config rather than in %SystemRoot%\System32 or a VirtualStore redirect. Development is unaffected: under cargo run the two directories are the same. :memory: and file: URIs are left alone. - Hand the db path to sqlx as a filesystem path instead of formatting it into a sqlite:// URL, which percent-decodes it and splits it on '?'. An installed path containing %20 previously opened a different file; verified it now does not. - Create the config's and the database's parent directories when missing, so a service can name /var/lib/runicgateway on a host where nothing made it yet. - 22 unit tests covering argument parsing, path anchoring, token persistence, the generated config template, and the --print-config document. No protocol change: PROTOCOL_VERSION stays 3. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
//! Terminates the loopback link to the ServUO shard and exposes a website-facing HTTP surface. So
|
||||
//! far: the shard link (bidirectional) and a WebSocket live feed. REST queries and SQLite come next.
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
mod rpc;
|
||||
mod shard;
|
||||
@@ -33,13 +34,48 @@ pub const PROTOCOL_VERSION: u32 = 3;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let args = match cli::parse(std::env::args().skip(1)) {
|
||||
Ok(args) => args,
|
||||
Err(msg) => {
|
||||
eprintln!("uo-link-sidecar: {msg}\n\n{}", cli::USAGE);
|
||||
std::process::exit(2);
|
||||
}
|
||||
};
|
||||
|
||||
match args.mode {
|
||||
cli::Mode::Help => {
|
||||
print!("{}", cli::USAGE);
|
||||
return Ok(());
|
||||
}
|
||||
cli::Mode::Version => {
|
||||
println!(
|
||||
"uo-link-sidecar {} (protocol {})",
|
||||
env!("CARGO_PKG_VERSION"),
|
||||
PROTOCOL_VERSION
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
// Tracing stays uninitialized here on purpose: the subscriber writes to stdout, and stdout
|
||||
// is the document. Config::load's messages are dropped rather than interleaved into JSON
|
||||
// an installer is about to parse — everything they would have said is in the document.
|
||||
cli::Mode::PrintConfig => {
|
||||
let loaded = config::Config::load(args.config.as_deref())?;
|
||||
println!("{:#}", config::describe(&loaded));
|
||||
return Ok(());
|
||||
}
|
||||
cli::Mode::Run => {}
|
||||
}
|
||||
|
||||
init_tracing();
|
||||
info!("uo-link sidecar starting");
|
||||
|
||||
let cfg = config::Config::load()?;
|
||||
let loaded = config::Config::load(args.config.as_deref())?;
|
||||
let cfg = loaded.cfg;
|
||||
info!(
|
||||
config = %loaded.path.display(),
|
||||
shard = %cfg.shard.bind,
|
||||
web = %cfg.web.bind,
|
||||
db = %cfg.store.path,
|
||||
auth = cfg.auth_required(),
|
||||
"configuration loaded"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user