rename modules to match behavior.
This commit is contained in:
parent
0b128ee2e1
commit
8e43820281
|
@ -0,0 +1,65 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::dns::DNSRecord;
|
||||||
|
|
||||||
|
pub enum Api {
|
||||||
|
Patch(DNSRecord),
|
||||||
|
Delete(DNSRecord),
|
||||||
|
Get(DNSRecord),
|
||||||
|
List(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct ResponseError {
|
||||||
|
pub code: String,
|
||||||
|
pub message: String,
|
||||||
|
pub fields: Vec<ResponseField>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct ResponseField {
|
||||||
|
#[serde(default)]
|
||||||
|
pub code: String,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub message: String,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub path: String,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
#[serde(rename = "pathRelated")]
|
||||||
|
pub path_related: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Api {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Api::Patch(record) => write!(
|
||||||
|
f,
|
||||||
|
"https://api.godaddy.com/v1/domains/{domain}/records",
|
||||||
|
domain = record.domain,
|
||||||
|
),
|
||||||
|
Api::Delete(record) => write!(
|
||||||
|
f,
|
||||||
|
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
||||||
|
domain = record.domain,
|
||||||
|
record_type = record.record_type,
|
||||||
|
name = record.name
|
||||||
|
),
|
||||||
|
Api::Get(record) => write!(
|
||||||
|
f,
|
||||||
|
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
||||||
|
domain = record.domain,
|
||||||
|
record_type = record.record_type,
|
||||||
|
name = record.name
|
||||||
|
),
|
||||||
|
Api::List(domain) => write!(
|
||||||
|
f,
|
||||||
|
"https://api.godaddy.com/v1/domains/{domain}/records",
|
||||||
|
domain = domain,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,65 +1,131 @@
|
||||||
use serde::Deserialize;
|
use crate::dns::DNSRecord;
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use crate::records::dns_record::DNSRecord;
|
pub mod api;
|
||||||
|
|
||||||
pub enum Api {
|
use log::{debug, info};
|
||||||
Patch(DNSRecord),
|
|
||||||
Delete(DNSRecord),
|
use crate::auth::Auth;
|
||||||
Get(DNSRecord),
|
use api::{Api, ResponseError};
|
||||||
List(String),
|
use reqwest::Response;
|
||||||
|
|
||||||
|
/// Sends a put request to the GoDaddy API to update a DNS record.
|
||||||
|
pub async fn update_record(record: DNSRecord, auth: &Auth) -> () {
|
||||||
|
let api: Api = Api::Patch(record.clone());
|
||||||
|
|
||||||
|
let body = vec![record.clone()];
|
||||||
|
debug!("{:?}", body);
|
||||||
|
|
||||||
|
let header = auth.as_header();
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
|
let req = client
|
||||||
|
.patch(api.to_string())
|
||||||
|
.json(&body)
|
||||||
|
.header("accept", "application/json")
|
||||||
|
.header("content-type", "application/json")
|
||||||
|
.header("authorization", &header);
|
||||||
|
debug!("{:?}", api.to_string());
|
||||||
|
|
||||||
|
let response = req.send().await.expect("Error updating records.");
|
||||||
|
parse_response(response, record).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
pub async fn delete_record(record: DNSRecord, auth: &Auth) -> () {
|
||||||
pub struct ResponseError {
|
let api: Api = Api::Delete(record.clone());
|
||||||
pub code: String,
|
|
||||||
pub message: String,
|
let header = auth.as_header();
|
||||||
pub fields: Vec<ResponseField>,
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
|
let req = client
|
||||||
|
.delete(api.to_string())
|
||||||
|
.header("accept", "application/json")
|
||||||
|
.header("authorization", &header);
|
||||||
|
|
||||||
|
let response = req.send().await.expect("Error deleting record.");
|
||||||
|
parse_response(response, record).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
async fn parse_response(response: Response, record: DNSRecord) -> () {
|
||||||
pub struct ResponseField {
|
match response.status() {
|
||||||
#[serde(default)]
|
s if s.is_success() => {
|
||||||
pub code: String,
|
info!("success: {:?}", record);
|
||||||
|
}
|
||||||
#[serde(default)]
|
s if s.is_client_error() => {
|
||||||
pub message: String,
|
let body = response.text().await.unwrap();
|
||||||
|
match serde_json::from_str::<ResponseError>(&body) {
|
||||||
#[serde(default)]
|
Ok(json) => {
|
||||||
pub path: String,
|
info!("client error [{}]: {}\n{:?}", s, json.message, json.fields);
|
||||||
|
}
|
||||||
#[serde(default)]
|
Err(e) => {
|
||||||
#[serde(rename = "pathRelated")]
|
eprintln!("Failed to parse JSON: {:?}", e);
|
||||||
pub path_related: String,
|
eprintln!("Raw response body: {:?}", body);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
impl fmt::Display for Api {
|
}
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
s => {
|
||||||
match self {
|
let body = response.text().await.unwrap();
|
||||||
Api::Patch(record) => write!(
|
match serde_json::from_str::<ResponseError>(&body) {
|
||||||
f,
|
Ok(json) => {
|
||||||
"https://api.godaddy.com/v1/domains/{domain}/records",
|
info!("client error [{}]: {}\n{:?}", s, json.message, json.fields);
|
||||||
domain = record.domain,
|
}
|
||||||
),
|
Err(e) => {
|
||||||
Api::Delete(record) => write!(
|
eprintln!("Failed to parse JSON: {:?}", e);
|
||||||
f,
|
eprintln!("Raw response body: {:?}", body);
|
||||||
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
}
|
||||||
domain = record.domain,
|
}
|
||||||
record_type = record.record_type,
|
|
||||||
name = record.name
|
|
||||||
),
|
|
||||||
Api::Get(record) => write!(
|
|
||||||
f,
|
|
||||||
"https://api.godaddy.com/v1/domains/{domain}/records/{record_type}/{name}",
|
|
||||||
domain = record.domain,
|
|
||||||
record_type = record.record_type,
|
|
||||||
name = record.name
|
|
||||||
),
|
|
||||||
Api::List(domain) => write!(
|
|
||||||
f,
|
|
||||||
"https://api.godaddy.com/v1/domains/{domain}/records",
|
|
||||||
domain = domain,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_record(record: &DNSRecord, auth: &Auth) -> Vec<DNSRecord> {
|
||||||
|
let api: Api = Api::Get(record.clone());
|
||||||
|
|
||||||
|
let header = auth.as_header();
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
|
let req = client
|
||||||
|
.get(api.to_string())
|
||||||
|
.header("accept", "application/json")
|
||||||
|
.header("authorization", &header);
|
||||||
|
|
||||||
|
let response = req.send().await.expect("Error listing records.");
|
||||||
|
if response.status().is_success() {
|
||||||
|
let data = &response.text().await.expect("Error reading response text");
|
||||||
|
let record: Vec<DNSRecord> = serde_json::from_str(data).expect("Error parsing response");
|
||||||
|
return record;
|
||||||
|
} else {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_records(domain: &str, auth: &Auth) -> () {
|
||||||
|
let api: Api = Api::List(domain.to_string());
|
||||||
|
|
||||||
|
let header = auth.as_header();
|
||||||
|
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
|
||||||
|
let req = client
|
||||||
|
.get(api.to_string())
|
||||||
|
.header("accept", "application/json")
|
||||||
|
.header("authorization", &header);
|
||||||
|
|
||||||
|
let response = req.send().await.expect("Error listing records.");
|
||||||
|
if response.status().is_success() {
|
||||||
|
let body = response.text().await.expect("Error reading response text");
|
||||||
|
let records: Vec<DNSRecord> = serde_json::from_str(&body).unwrap();
|
||||||
|
// .expect("Error parsing records into object");
|
||||||
|
println!("{:<5} {:<25} {:<30}", "Type", "Name", "Value"); // Header
|
||||||
|
for record in records {
|
||||||
|
println!(
|
||||||
|
"{:<5} {:<25} {:<30}",
|
||||||
|
record.record_type, record.name, record.data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("Request failed with status: {}", response.status());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
extern crate dotenv;
|
use clap::{Parser, Subcommand};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
@ -8,13 +8,11 @@ use log::LevelFilter;
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
|
mod dns;
|
||||||
mod godaddy;
|
mod godaddy;
|
||||||
mod ip_handler;
|
|
||||||
pub mod records;
|
|
||||||
use crate::auth::Auth;
|
|
||||||
use records::dns_record::{DNSRecord, RecordType};
|
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use auth::Auth;
|
||||||
|
use dns::{DNSRecord, RecordType};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(
|
#[clap(
|
||||||
|
@ -107,7 +105,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
ttl: 600,
|
ttl: 600,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
records::update_record(record, &auth).await;
|
godaddy::update_record(record, &auth).await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
SubCommands::Delete(args) => {
|
SubCommands::Delete(args) => {
|
||||||
|
@ -117,12 +115,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
record_type: args.record_type,
|
record_type: args.record_type,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
records::delete_record(record, &auth).await;
|
godaddy::delete_record(record, &auth).await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
SubCommands::List(args) => {
|
SubCommands::List(args) => {
|
||||||
let domain = args.domain;
|
let domain = args.domain;
|
||||||
records::list_records(&domain, &auth).await;
|
godaddy::list_records(&domain, &auth).await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
use log::{debug, info};
|
|
||||||
|
|
||||||
use crate::auth::Auth;
|
|
||||||
use crate::godaddy::{Api, ResponseError};
|
|
||||||
use crate::records::dns_record::DNSRecord;
|
|
||||||
use reqwest::Response;
|
|
||||||
|
|
||||||
pub mod dns_record;
|
|
||||||
|
|
||||||
/// Sends a put request to the GoDaddy API to update a DNS record.
|
|
||||||
pub async fn update_record(record: DNSRecord, auth: &Auth) -> () {
|
|
||||||
let api: Api = Api::Patch(record.clone());
|
|
||||||
|
|
||||||
let body = vec![record.clone()];
|
|
||||||
debug!("{:?}", body);
|
|
||||||
|
|
||||||
let header = auth.as_header();
|
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
|
||||||
|
|
||||||
let req = client
|
|
||||||
.patch(api.to_string())
|
|
||||||
.json(&body)
|
|
||||||
.header("accept", "application/json")
|
|
||||||
.header("content-type", "application/json")
|
|
||||||
.header("authorization", &header);
|
|
||||||
debug!("{:?}", api.to_string());
|
|
||||||
|
|
||||||
let response = req.send().await.expect("Error updating records.");
|
|
||||||
parse_response(response, record).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn delete_record(record: DNSRecord, auth: &Auth) -> () {
|
|
||||||
let api: Api = Api::Delete(record.clone());
|
|
||||||
|
|
||||||
let header = auth.as_header();
|
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
|
||||||
|
|
||||||
let req = client
|
|
||||||
.delete(api.to_string())
|
|
||||||
.header("accept", "application/json")
|
|
||||||
.header("authorization", &header);
|
|
||||||
|
|
||||||
let response = req.send().await.expect("Error deleting record.");
|
|
||||||
parse_response(response, record).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn parse_response(response: Response, record: DNSRecord) -> () {
|
|
||||||
match response.status() {
|
|
||||||
s if s.is_success() => {
|
|
||||||
info!("success: {:?}", record);
|
|
||||||
}
|
|
||||||
s if s.is_client_error() => {
|
|
||||||
let body = response.text().await.unwrap();
|
|
||||||
match serde_json::from_str::<ResponseError>(&body) {
|
|
||||||
Ok(json) => {
|
|
||||||
info!("client error [{}]: {}\n{:?}", s, json.message, json.fields);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to parse JSON: {:?}", e);
|
|
||||||
eprintln!("Raw response body: {:?}", body);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
s => {
|
|
||||||
let body = response.text().await.unwrap();
|
|
||||||
match serde_json::from_str::<ResponseError>(&body) {
|
|
||||||
Ok(json) => {
|
|
||||||
info!("client error [{}]: {}\n{:?}", s, json.message, json.fields);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Failed to parse JSON: {:?}", e);
|
|
||||||
eprintln!("Raw response body: {:?}", body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_record(record: &DNSRecord, auth: &Auth) -> Vec<DNSRecord> {
|
|
||||||
let api: Api = Api::Get(record.clone());
|
|
||||||
|
|
||||||
let header = auth.as_header();
|
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
|
||||||
|
|
||||||
let req = client
|
|
||||||
.get(api.to_string())
|
|
||||||
.header("accept", "application/json")
|
|
||||||
.header("authorization", &header);
|
|
||||||
|
|
||||||
let response = req.send().await.expect("Error listing records.");
|
|
||||||
if response.status().is_success() {
|
|
||||||
let data = &response.text().await.expect("Error reading response text");
|
|
||||||
let record: Vec<DNSRecord> = serde_json::from_str(data).expect("Error parsing response");
|
|
||||||
return record;
|
|
||||||
} else {
|
|
||||||
return vec![];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn list_records(domain: &str, auth: &Auth) -> () {
|
|
||||||
let api: Api = Api::List(domain.to_string());
|
|
||||||
|
|
||||||
let header = auth.as_header();
|
|
||||||
|
|
||||||
let client = reqwest::Client::new();
|
|
||||||
|
|
||||||
let req = client
|
|
||||||
.get(api.to_string())
|
|
||||||
.header("accept", "application/json")
|
|
||||||
.header("authorization", &header);
|
|
||||||
|
|
||||||
let response = req.send().await.expect("Error listing records.");
|
|
||||||
if response.status().is_success() {
|
|
||||||
let body = response.text().await.expect("Error reading response text");
|
|
||||||
let records: Vec<DNSRecord> = serde_json::from_str(&body).unwrap();
|
|
||||||
// .expect("Error parsing records into object");
|
|
||||||
println!("{:<5} {:<25} {:<30}", "Type", "Name", "Value"); // Header
|
|
||||||
for record in records {
|
|
||||||
println!(
|
|
||||||
"{:<5} {:<25} {:<30}",
|
|
||||||
record.record_type, record.name, record.data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Request failed with status: {}", response.status());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue