attic/server/src/main.rs

124 lines
3.4 KiB
Rust
Raw Normal View History

2023-01-01 00:01:07 +00:00
use std::env;
use std::net::SocketAddr;
use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, ValueEnum};
use tokio::join;
use attic_server::config;
/// Nix binary cache server.
#[derive(Debug, Parser)]
#[clap(version, author = "Zhaofeng Li <hello@zhaofeng.li>")]
#[clap(propagate_version = true)]
struct Opts {
/// Path to the config file.
#[clap(short = 'f', long)]
config: Option<PathBuf>,
/// Socket address to listen on.
///
/// This overrides `listen` in the config.
#[clap(short = 'l', long)]
listen: Option<SocketAddr>,
/// Mode to run.
#[clap(long, default_value = "monolithic")]
mode: ServerMode,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
enum ServerMode {
/// Run all components.
Monolithic,
/// Run the API server.
ApiServer,
/// Run the garbage collector periodically.
GarbageCollector,
/// Run the database migrations then exit.
DbMigrations,
/// Run garbage collection then exit.
GarbageCollectorOnce,
2023-01-02 03:59:02 +00:00
/// Check the configuration then exit.
CheckConfig,
2023-01-01 00:01:07 +00:00
}
#[tokio::main]
async fn main() -> Result<()> {
init_logging();
dump_version();
let opts = Opts::parse();
let config = if let Some(config_path) = opts.config {
config::load_config_from_path(&config_path)
} else if let Ok(config_env) = env::var("ATTIC_SERVER_CONFIG_BASE64") {
let decoded = String::from_utf8(base64::decode(config_env.as_bytes())?)?;
config::load_config_from_str(&decoded)
} else {
// Config from XDG
let config_path = config::get_xdg_config_path()?;
if opts.mode == ServerMode::Monolithic {
// Special OOBE sequence
attic_server::oobe::run_oobe().await?;
} else if !config_path.exists() {
eprintln!("You haven't specified a config file (--config/-f), and the XDG config file doesn't exist.");
eprintln!("Hint: To automatically set up Attic, run `atticd` without any arguments.");
}
config::load_config_from_path(&config_path)
};
match opts.mode {
ServerMode::Monolithic => {
attic_server::run_migrations(config.clone()).await?;
let (api_server, _) = join!(
attic_server::run_api_server(opts.listen, config.clone()),
attic_server::gc::run_garbage_collection(config.clone()),
);
api_server?;
}
ServerMode::ApiServer => {
attic_server::run_api_server(opts.listen, config).await?;
}
ServerMode::GarbageCollector => {
attic_server::gc::run_garbage_collection(config.clone()).await;
}
ServerMode::DbMigrations => {
attic_server::run_migrations(config).await?;
}
ServerMode::GarbageCollectorOnce => {
attic_server::gc::run_garbage_collection_once(config).await?;
}
2023-01-02 03:59:02 +00:00
ServerMode::CheckConfig => {
// config is valid, let's just exit :)
}
2023-01-01 00:01:07 +00:00
}
Ok(())
}
fn init_logging() {
#[cfg(not(feature = "tokio-console"))]
tracing_subscriber::fmt::init();
#[cfg(feature = "tokio-console")]
console_subscriber::init();
}
fn dump_version() {
#[cfg(debug_assertions)]
eprintln!("Attic Server {} (debug)", env!("CARGO_PKG_VERSION"));
#[cfg(not(debug_assertions))]
eprintln!("Attic Server {} (release)", env!("CARGO_PKG_VERSION"));
}