feat: Use anyhow for error handling

This commit is contained in:
Rostislav Raykov 2020-03-22 22:10:50 +01:00
parent 601445e973
commit cfd5cb9da9
3 changed files with 33 additions and 25 deletions

View file

@ -1,12 +1,18 @@
use failure::Error;
use quicli::fs::{write_to_file, read_file};
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
use anyhow::Result;
pub fn read_cache_file(path: &PathBuf) -> Result<String, Error> {
Ok(read_file(path)?)
pub fn read_file(path: &PathBuf) -> Result<String> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
pub fn write_cache_file(path: &PathBuf, ip: &str) -> Result<(), Error> {
write_to_file(path, ip)?;
pub fn write_file(path: &PathBuf, ip: &str) -> Result<()> {
let mut file = File::create(path)?;
file.write_all(ip.as_bytes())?;
Ok(())
}

View file

@ -1,13 +1,13 @@
mod file;
mod network;
use file::{read_cache_file, write_cache_file};
use file::{read_file, write_file};
use human_panic::setup_panic;
use network::{get_current_ip, get_dns_record_id, get_zone_identifier, update_ddns};
use quicli::fs::read_file;
use quicli::prelude::*;
use std::path::PathBuf;
use structopt::StructOpt;
use anyhow::{Context, Result};
#[derive(Deserialize)]
struct Config {
@ -45,7 +45,7 @@ struct Cli {
cache: Option<PathBuf>,
}
fn main() -> CliResult {
fn main() -> Result<()> {
setup_panic!();
let args = Cli::from_args();
@ -53,7 +53,7 @@ fn main() -> CliResult {
let cached_ip: Option<String> = match args.cache.clone() {
Some(v) => {
if v.exists() {
Some(read_cache_file(&v.clone())?)
Some(read_file(&v.clone()).context("Could not read cache file")?)
} else {
Some("0.0.0.0".to_owned())
}
@ -73,12 +73,12 @@ fn main() -> CliResult {
&current_ip,
&args.cache.clone().unwrap()
);
write_cache_file(&args.cache.unwrap(), &current_ip)?;
write_file(&args.cache.unwrap(), &current_ip)?;
}
let (email, auth_key, zone, domain) = match args.config {
Some(c) => {
let config_str = read_file(c)?;
let config_str = read_file(&c)?;
let config: Config = toml::from_str(&config_str)?;
(config.email, config.auth_key, config.zone, config.domain)
}
@ -106,9 +106,9 @@ fn update(
auth_key: &str,
zone: &str,
domain: &str,
) -> Result<(), Error> {
let zone_id = get_zone_identifier(&zone, &email, &auth_key)?;
let record_id = get_dns_record_id(&zone_id, &domain, &email, &auth_key)?;
) -> Result<()> {
let zone_id = get_zone_identifier(&zone, &email, &auth_key).context("Error getting the zone identifier")?;
let record_id = get_dns_record_id(&zone_id, &domain, &email, &auth_key).context("Error getting the DNS record ID")?;
update_ddns(
&current_ip,
@ -117,7 +117,7 @@ fn update(
&record_id,
&email,
&auth_key,
)?;
).context("Error updating the DNS record")?;
Ok(())
}

View file

@ -1,5 +1,5 @@
use failure::{format_err, Error};
use serde_derive::{Deserialize, Serialize};
use anyhow::{anyhow};
#[derive(Deserialize, Debug)]
struct CloudflareListResponse {
@ -28,7 +28,7 @@ struct UpdateIpData {
content: String,
}
pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> Result<String, Error> {
pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> anyhow::Result<String> {
let client = reqwest::blocking::Client::new();
let url = format!("https://api.cloudflare.com/client/v4/zones?name={}", zone);
let response: CloudflareListResponse = client
@ -38,13 +38,14 @@ pub fn get_zone_identifier(zone: &str, email: &str, key: &str) -> Result<String,
.header("Content-Type", "application/json")
.send()?
.json()?;
if !response.success {
let err: String = response
.errors
.iter()
.map(|s| format!("{}\n", s.to_owned()))
.collect();
return Err(format_err!("API Error: {}", err));
return Err(anyhow!("API Error: {}", err));
}
Ok(response.result[0].id.clone())
@ -55,7 +56,7 @@ pub fn get_dns_record_id(
domain: &str,
email: &str,
key: &str,
) -> Result<String, Error> {
) -> anyhow::Result<String> {
let client = reqwest::blocking::Client::new();
let url = format!(
"https://api.cloudflare.com/client/v4/zones/{}/dns_records?name={}",
@ -68,19 +69,20 @@ pub fn get_dns_record_id(
.header("Content-Type", "application/json")
.send()?
.json()?;
if !response.success {
let err: String = response
.errors
.iter()
.map(|s| format!("{}\n", s.to_owned()))
.collect();
return Err(format_err!("API Error: {}", err));
return Err(anyhow!("API Error: {}", err));
}
let id = match response.result.first() {
Some(v) => v.id.clone(),
None => {
return Err(format_err!(
return Err(anyhow!(
"Unexpected API result for DNS record. Check if you passed the right options."
))
}
@ -89,7 +91,7 @@ pub fn get_dns_record_id(
Ok(id)
}
pub fn get_current_ip() -> Result<String, Error> {
pub fn get_current_ip() -> anyhow::Result<String> {
Ok(reqwest::blocking::Client::new()
.get("http://ipv4.icanhazip.com")
.send()?
@ -105,7 +107,7 @@ pub fn update_ddns(
record_id: &str,
email: &str,
key: &str,
) -> Result<(), Error> {
) -> anyhow::Result<()> {
let client = reqwest::blocking::Client::new();
let url = format!(
"https://api.cloudflare.com/client/v4/zones/{}/dns_records/{}",
@ -134,7 +136,7 @@ pub fn update_ddns(
.iter()
.map(|s| format!("{}\n", s.to_owned()))
.collect();
return Err(format_err!("Unsuccessful update of DNS record: {}", err));
return Err(anyhow!("Unsuccessful update of DNS record: {}", err));
}
Ok(())