rename modules to match behavior.

This commit is contained in:
publicmatt 2024-04-03 07:46:08 -07:00
parent 0b128ee2e1
commit 8e43820281
6 changed files with 194 additions and 195 deletions

65
src/godaddy/api.rs Normal file
View File

@ -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,
),
}
}
}

View File

@ -1,65 +1,131 @@
use serde::Deserialize;
use std::fmt;
use crate::dns::DNSRecord;
use crate::records::dns_record::DNSRecord;
pub mod api;
pub enum Api {
Patch(DNSRecord),
Delete(DNSRecord),
Get(DNSRecord),
List(String),
use log::{debug, info};
use crate::auth::Auth;
use api::{Api, ResponseError};
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 struct ResponseError {
pub code: String,
pub message: String,
pub fields: Vec<ResponseField>,
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;
}
#[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,
async fn parse_response(response: Response, record: DNSRecord) -> () {
match response.status() {
s if s.is_success() => {
info!("success: {:?}", record);
}
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,
),
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());
}
}

View File

@ -1,4 +1,4 @@
extern crate dotenv;
use clap::{Parser, Subcommand};
use dotenv::dotenv;
use std::env;
@ -8,13 +8,11 @@ use log::LevelFilter;
use simple_logger::SimpleLogger;
mod auth;
mod dns;
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)]
#[clap(
@ -107,7 +105,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
ttl: 600,
..Default::default()
};
records::update_record(record, &auth).await;
godaddy::update_record(record, &auth).await;
return Ok(());
}
SubCommands::Delete(args) => {
@ -117,12 +115,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
record_type: args.record_type,
..Default::default()
};
records::delete_record(record, &auth).await;
godaddy::delete_record(record, &auth).await;
return Ok(());
}
SubCommands::List(args) => {
let domain = args.domain;
records::list_records(&domain, &auth).await;
godaddy::list_records(&domain, &auth).await;
return Ok(());
}
}

View File

@ -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());
}
}