Skip to content

Commit

Permalink
add a proper commandline interface
Browse files Browse the repository at this point in the history
  • Loading branch information
dotzenith committed Aug 30, 2024
1 parent c64c8e4 commit 4be26e5
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 20 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ serde_json = "1.0.127"
config = { version = "0.14", default-features = false, features = ["yaml"] }
simplelog = "0.12.2"
log = "0.4.22"
clap = { version = "4.5.16", features = ["cargo"] }
9 changes: 5 additions & 4 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{Context, Result};
use reqwest::blocking::get;
use simplelog::{TermLogger, WriteLogger, LevelFilter, Config, TerminalMode, ColorChoice};
use std::fs::File;
use simplelog::{ColorChoice, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger};
use std::fs::OpenOptions;
use std::process;

pub fn get_ip() -> Result<String> {
Expand All @@ -13,10 +13,11 @@ pub fn get_ip() -> Result<String> {
.to_owned())
}

pub fn init_logger(file: Option<&str>) {
pub fn init_logger(file: Option<&String>) {
match file {
Some(file_path) => {
let file = File::create(file_path);
let file = OpenOptions::new().create(true).append(true).open(file_path);

if file.is_err() {
eprintln!("Unable to create log file");
process::exit(1);
Expand Down
8 changes: 4 additions & 4 deletions src/config_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct CloudflareConfig {
pub api_key: String,
pub zone_name: String,
pub key: String,
pub zone: String,
pub hostname: String,
pub ttl: u32,
pub proxied: bool,
Expand All @@ -30,9 +30,9 @@ pub struct Settings {
pub duckdns: Option<Vec<DuckDNSConfig>>,
}

pub fn config() -> Result<Settings, ConfigError> {
pub fn config(path: &str) -> Result<Settings, ConfigError> {
let settings = Config::builder()
.add_source(File::new("example.yaml", FileFormat::Yaml))
.add_source(File::new(path, FileFormat::Yaml))
.build()?;

let settings: Settings = settings.try_deserialize()?;
Expand Down
37 changes: 31 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,45 @@ mod config_manager;
mod providers;

use crate::providers::{CloudflareManager, DuckdnsManager, NamecheapManager};
use reqwest::blocking::Client;
use clap::{arg, command};
use common::init_logger;
use log::{error, info};
use reqwest::blocking::Client;

fn main() {
let settings = config_manager::config().unwrap();
let matches = command!()
.arg_required_else_help(true)
.arg(
arg!(-c --config <CONFIG>)
.required(true)
.help("The yaml config file to use"),
)
.arg(
arg!(-l --log <LOGFILE>)
.required(false)
.help("Where the output will be logged, uses stdout if not used"),
)
.get_matches();

// Required so unwrap is swell
let config: &String = matches.get_one("config").unwrap();
let log: Option<&String> = matches.get_one("log");

let settings = match config_manager::config(config) {
Ok(set) => set,
Err(err) => {
eprintln!("Config Error: {:?}", err);
std::process::exit(1);
}
};
let client = Client::new();
init_logger(None);
init_logger(log); // Will exit if it doesn't succeed

if let Some(cloudflare) = settings.cloudflare {
for config in cloudflare.iter() {
match CloudflareManager::new(&client).update_dns_record(config) {
Ok(ok) => info!("Cloudflare: {}", ok),
Err(err) => error!("Cloudflare: {}", err)
Err(err) => error!("Cloudflare: {}", err),
}
}
}
Expand All @@ -25,7 +50,7 @@ fn main() {
for config in namecheap.iter() {
match NamecheapManager::new(&client).update_dns_record(config) {
Ok(ok) => info!("Namecheap: {}", ok),
Err(err) => error!("Namecheap: {}", err)
Err(err) => error!("Namecheap: {}", err),
}
}
}
Expand All @@ -34,7 +59,7 @@ fn main() {
for config in duckdns.iter() {
match DuckdnsManager::new(&client).update_dns_record(config) {
Ok(ok) => info!("Duckdns: {}", ok),
Err(err) => error!("Duckdns: {}", err)
Err(err) => error!("Duckdns: {}", err),
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/providers/cloudflare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ impl<'a> CloudflareManager<'a> {
Err(anyhow!("Could not find record id"))
}
pub fn update_dns_record(&self, config: &CloudflareConfig) -> Result<String> {
let zone_id = self.get_zone_id(&config.api_key, &config.zone_name)?;
let zone_id = self.get_zone_id(&config.key, &config.zone)?;
let (record_id, current_ip) =
self.get_dns_record_id_and_ip(&zone_id, &config.hostname, &config.api_key)?;
self.get_dns_record_id_and_ip(&zone_id, &config.hostname, &config.key)?;
let ip = get_ip()?;

if current_ip == ip {
Expand All @@ -93,7 +93,7 @@ impl<'a> CloudflareManager<'a> {
.client
.patch(&url)
.header("Content-Type", "application/json")
.header("Authorization", format!("Bearer {}", &config.api_key))
.header("Authorization", format!("Bearer {}", &config.key))
.json(&json!({
"content": ip,
"name": &config.hostname,
Expand All @@ -110,8 +110,8 @@ impl<'a> CloudflareManager<'a> {

if success {
return Ok(format!(
"Success! {} has been set to {}",
&config.hostname, ip
"Success! Hostname: {} for Zone: {} has been set to {}",
&config.hostname, &config.zone, ip
))
}
Err(anyhow!("Update failed: {}", json.to_string()))
Expand Down
2 changes: 1 addition & 1 deletion src/providers/namecheap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'a> NamecheapManager<'a> {
.context("Did not find any IP Addresses in response")?;

if &captures[1] == ip {
Ok(format!("Success! {} has been set to {}", &config.host, ip))
Ok(format!("Success! Host: {} for Domain: {} has been set to {}", &config.host, &config.domain, ip))
} else {
Err(anyhow!("IP Address returned by the XML does not match"))
}
Expand Down

0 comments on commit 4be26e5

Please sign in to comment.