fix(clippy): split code a bit
All checks were successful
/ build (push) Successful in 1s
/ check-integration-tests (push) Successful in 10s
/ report-size (push) Successful in 2s

Main was too big for clippy
This commit is contained in:
Jalil David Salamé Messina 2025-06-07 00:18:05 +02:00
parent ae0dbf3bd9
commit 74cf34edff
Signed by: jalil
GPG key ID: F016B9E770737A0B

View file

@ -128,7 +128,7 @@ impl SavedIPs {
.chain(self.ipv6.map(IpAddr::V6)) .chain(self.ipv6.map(IpAddr::V6))
} }
fn from_str(data: &str) -> miette::Result<Self> { fn from_str(data: &str) -> Result<Self> {
match data.parse::<IpAddr>() { match data.parse::<IpAddr>() {
// Old format // Old format
Ok(IpAddr::V4(ipv4)) => Ok(Self { Ok(IpAddr::V4(ipv4)) => Ok(Self {
@ -145,7 +145,7 @@ impl SavedIPs {
} }
impl AppState<'static> { impl AppState<'static> {
fn from_args(args: &Opts, config: &config::Config) -> miette::Result<Self> { fn from_args(args: &Opts, config: &config::Config) -> Result<Self> {
let Opts { let Opts {
verbosity: _, verbosity: _,
data_dir, data_dir,
@ -180,7 +180,7 @@ impl AppState<'static> {
// Load keyfile // Load keyfile
key_file: key_file key_file: key_file
.as_deref() .as_deref()
.map(|path| -> miette::Result<_> { .map(|path| -> Result<_> {
std::fs::File::open(path) std::fs::File::open(path)
.into_diagnostic() .into_diagnostic()
.wrap_err_with(|| { .wrap_err_with(|| {
@ -255,6 +255,18 @@ impl std::str::FromStr for Ipv6Prefix {
} }
} }
fn load_password(path: &Path) -> Result<Box<[u8]>> {
let pass = std::fs::read_to_string(path).into_diagnostic()?;
let pass: Box<[u8]> = URL_SAFE_NO_PAD
.decode(pass.trim().as_bytes())
.into_diagnostic()
.wrap_err_with(|| format!("failed to decode password from {}", path.display()))?
.into();
Ok(pass)
}
#[tracing::instrument(err)] #[tracing::instrument(err)]
fn main() -> Result<()> { fn main() -> Result<()> {
// set panic hook to pretty print with miette's formatter // set panic hook to pretty print with miette's formatter
@ -310,18 +322,8 @@ fn main() -> Result<()> {
let password_hash = config let password_hash = config
.password .password
.password_file .password_file
.map(|path| -> miette::Result<_> { .as_deref()
let path = path.as_path(); .map(load_password)
let pass = std::fs::read_to_string(path).into_diagnostic()?;
let pass: Box<[u8]> = URL_SAFE_NO_PAD
.decode(pass.trim().as_bytes())
.into_diagnostic()
.wrap_err_with(|| format!("failed to decode password from {}", path.display()))?
.into();
Ok(pass)
})
.transpose() .transpose()
.wrap_err("failed to load password hash")?; .wrap_err("failed to load password hash")?;
@ -336,63 +338,70 @@ fn main() -> Result<()> {
.into_diagnostic() .into_diagnostic()
.wrap_err("failed to start the tokio runtime")?; .wrap_err("failed to start the tokio runtime")?;
rt.block_on(async { rt.block_on(async_main(state, config, password_hash))
// Update DNS record with previous IPs (if available) .wrap_err("failed to run main loop")
let ips = state.last_ips.lock().await.clone(); }
let mut actions = ips #[tracing::instrument(err, skip(state, pass))]
.ips() async fn async_main(
.filter(|ip| config.records.ip_type.valid_for_type(*ip)) state: AppState<'static>,
.flat_map(|ip| nsupdate::Action::from_records(ip, state.ttl, state.records)) config: Config,
.peekable(); pass: Option<Box<[u8]>>,
) -> Result<()> {
// Update DNS record with previous IPs (if available)
let ips = state.last_ips.lock().await.clone();
if actions.peek().is_some() { let mut actions = ips
match nsupdate::nsupdate(state.key_file, actions).await { .ips()
Ok(status) => { .filter(|ip| config.records.ip_type.valid_for_type(*ip))
if !status.success() { .flat_map(|ip| nsupdate::Action::from_records(ip, state.ttl, state.records))
error!("nsupdate failed: code {status}"); .peekable();
bail!("nsupdate returned with code {status}");
} if actions.peek().is_some() {
} match nsupdate::nsupdate(state.key_file, actions).await {
Err(err) => { Ok(status) => {
error!("Failed to update records with previous IP: {err}"); if !status.success() {
return Err(err) error!("nsupdate failed: code {status}");
.into_diagnostic() bail!("nsupdate returned with code {status}");
.wrap_err("failed to update records with previous IP");
} }
} }
Err(err) => {
error!("Failed to update records with previous IP: {err}");
return Err(err)
.into_diagnostic()
.wrap_err("failed to update records with previous IP");
}
} }
}
// Create services // Create services
let app = Router::new().route("/update", get(update_records)); let app = Router::new().route("/update", get(update_records));
// if a password is provided, validate it // if a password is provided, validate it
let app = if let Some(pass) = password_hash { let app = if let Some(pass) = pass {
app.layer(auth::layer( app.layer(auth::layer(
Box::leak(pass), Box::leak(pass),
Box::leak(config.password.salt), Box::leak(config.password.salt),
)) ))
} else { } else {
app app
} }
.layer(config.records.ip_source.into_extension()) .layer(config.records.ip_source.into_extension())
.with_state(state); .with_state(state);
let config::Server { address } = config.server; let config::Server { address } = config.server;
// Start services // Start services
info!("starting listener on {address}"); info!("starting listener on {address}");
let listener = tokio::net::TcpListener::bind(address) let listener = tokio::net::TcpListener::bind(address)
.await
.into_diagnostic()?;
info!("listening on {address}");
axum::serve(
listener,
app.into_make_service_with_connect_info::<SocketAddr>(),
)
.await .await
.into_diagnostic() .into_diagnostic()?;
}) info!("listening on {address}");
.wrap_err("failed to run main loop") axum::serve(
listener,
app.into_make_service_with_connect_info::<SocketAddr>(),
)
.await
.into_diagnostic()
} }
/// Serde deserialization decorator to map empty Strings to None, /// Serde deserialization decorator to map empty Strings to None,