fix(clippy): split code a bit
Main was too big for clippy
This commit is contained in:
parent
ae0dbf3bd9
commit
74cf34edff
1 changed files with 72 additions and 63 deletions
135
src/main.rs
135
src/main.rs
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue