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 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,
|
||||
}
|
||||
|
||||
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,
|
||||
),
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -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(());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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