mirror of
https://github.com/SeriousBug/gandi-live-dns-rust
synced 2024-10-31 14:17:25 -05:00
Avoid multiple main versions & concurrently get ipv4 and ipv6 addresses (#87)
* Avoid having multiple versions of main run function * Concurrently get ipv4 and ipv6 addresses
This commit is contained in:
parent
7e7a9da65e
commit
f8060fad42
|
@ -2,7 +2,7 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use super::ip_source::IPSource;
|
use super::ip_source::IPSource;
|
||||||
|
|
||||||
pub(crate) struct IPSourceIcanhazip {}
|
pub(crate) struct IPSourceIcanhazip;
|
||||||
|
|
||||||
async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
||||||
let response = reqwest::get(api_url).await?;
|
let response = reqwest::get(api_url).await?;
|
||||||
|
@ -12,14 +12,14 @@ async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl IPSource for IPSourceIcanhazip {
|
impl IPSource for IPSourceIcanhazip {
|
||||||
async fn get_ipv4() -> anyhow::Result<String> {
|
async fn get_ipv4(&self) -> anyhow::Result<String> {
|
||||||
Ok(get_ip("https://ipv4.icanhazip.com")
|
Ok(get_ip("https://ipv4.icanhazip.com")
|
||||||
.await?
|
.await?
|
||||||
// icanazip puts a newline at the end
|
// icanazip puts a newline at the end
|
||||||
.trim()
|
.trim()
|
||||||
.to_string())
|
.to_string())
|
||||||
}
|
}
|
||||||
async fn get_ipv6() -> anyhow::Result<String> {
|
async fn get_ipv6(&self) -> anyhow::Result<String> {
|
||||||
Ok(get_ip("https://ipv6.icanhazip.com")
|
Ok(get_ip("https://ipv6.icanhazip.com")
|
||||||
.await?
|
.await?
|
||||||
// icanazip puts a newline at the end
|
// icanazip puts a newline at the end
|
||||||
|
@ -32,13 +32,15 @@ impl IPSource for IPSourceIcanhazip {
|
||||||
mod tests {
|
mod tests {
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use super::IPSource;
|
use crate::ip_source::ip_source::IPSource;
|
||||||
|
|
||||||
use super::IPSourceIcanhazip;
|
use super::IPSourceIcanhazip;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
async fn ipv4_test() {
|
async fn ipv4_test() {
|
||||||
let ipv4 = IPSourceIcanhazip::get_ipv4()
|
let ipv4 = IPSourceIcanhazip
|
||||||
|
.get_ipv4()
|
||||||
.await
|
.await
|
||||||
.expect("Failed to get the IP address");
|
.expect("Failed to get the IP address");
|
||||||
assert!(Regex::new(r"^\d+[.]\d+[.]\d+[.]\d+$")
|
assert!(Regex::new(r"^\d+[.]\d+[.]\d+[.]\d+$")
|
||||||
|
@ -49,7 +51,8 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
async fn ipv6_test() {
|
async fn ipv6_test() {
|
||||||
let ipv6 = IPSourceIcanhazip::get_ipv6()
|
let ipv6 = IPSourceIcanhazip
|
||||||
|
.get_ipv6()
|
||||||
.await
|
.await
|
||||||
.expect("Failed to get the IP address");
|
.expect("Failed to get the IP address");
|
||||||
assert!(Regex::new(r"^([0-9a-fA-F]*:){7}[0-9a-fA-F]*$")
|
assert!(Regex::new(r"^([0-9a-fA-F]*:){7}[0-9a-fA-F]*$")
|
||||||
|
|
|
@ -2,6 +2,6 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait IPSource {
|
pub trait IPSource {
|
||||||
async fn get_ipv4() -> anyhow::Result<String>;
|
async fn get_ipv4(&self) -> anyhow::Result<String>;
|
||||||
async fn get_ipv6() -> anyhow::Result<String>;
|
async fn get_ipv6(&self) -> anyhow::Result<String>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use async_trait::async_trait;
|
||||||
|
|
||||||
use super::ip_source::IPSource;
|
use super::ip_source::IPSource;
|
||||||
|
|
||||||
pub(crate) struct IPSourceIpify {}
|
pub(crate) struct IPSourceIpify;
|
||||||
|
|
||||||
async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
||||||
let response = reqwest::get(api_url).await?;
|
let response = reqwest::get(api_url).await?;
|
||||||
|
@ -12,10 +12,10 @@ async fn get_ip(api_url: &str) -> anyhow::Result<String> {
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl IPSource for IPSourceIpify {
|
impl IPSource for IPSourceIpify {
|
||||||
async fn get_ipv4() -> anyhow::Result<String> {
|
async fn get_ipv4(&self) -> anyhow::Result<String> {
|
||||||
get_ip("https://api.ipify.org").await
|
get_ip("https://api.ipify.org").await
|
||||||
}
|
}
|
||||||
async fn get_ipv6() -> anyhow::Result<String> {
|
async fn get_ipv6(&self) -> anyhow::Result<String> {
|
||||||
get_ip("https://api6.ipify.org").await
|
get_ip("https://api6.ipify.org").await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
async fn ipv4_test() {
|
async fn ipv4_test() {
|
||||||
let ipv4 = IPSourceIpify::get_ipv4()
|
let ipv4 = IPSourceIpify
|
||||||
|
.get_ipv4()
|
||||||
.await
|
.await
|
||||||
.expect("Failed to get the IP address");
|
.expect("Failed to get the IP address");
|
||||||
assert!(Regex::new(r"^\d+[.]\d+[.]\d+[.]\d+$")
|
assert!(Regex::new(r"^\d+[.]\d+[.]\d+[.]\d+$")
|
||||||
|
@ -41,7 +42,8 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
async fn ipv6_test() {
|
async fn ipv6_test() {
|
||||||
let ipv6 = IPSourceIpify::get_ipv6()
|
let ipv6 = IPSourceIpify
|
||||||
|
.get_ipv6()
|
||||||
.await
|
.await
|
||||||
.expect("Failed to get the IP address");
|
.expect("Failed to get the IP address");
|
||||||
assert!(Regex::new(r"^([0-9a-fA-F]*:){7}[0-9a-fA-F]*$")
|
assert!(Regex::new(r"^([0-9a-fA-F]*:){7}[0-9a-fA-F]*$")
|
||||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -7,6 +7,7 @@ use ip_source::icanhazip::IPSourceIcanhazip;
|
||||||
use reqwest::{header, Client, ClientBuilder, StatusCode};
|
use reqwest::{header, Client, ClientBuilder, StatusCode};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::{num::NonZeroU32, sync::Arc, time::Duration};
|
use std::{num::NonZeroU32, sync::Arc, time::Duration};
|
||||||
|
use tokio::join;
|
||||||
use tokio::{self, task::JoinHandle, time::sleep};
|
use tokio::{self, task::JoinHandle, time::sleep};
|
||||||
mod config;
|
mod config;
|
||||||
mod gandi;
|
mod gandi;
|
||||||
|
@ -39,11 +40,10 @@ pub struct APIPayload {
|
||||||
pub rrset_ttl: u32,
|
pub rrset_ttl: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run<IP: IPSource>(base_url: &str, conf: &Config) -> anyhow::Result<()> {
|
async fn run(base_url: &str, ip_source: &Box<dyn IPSource>, conf: &Config) -> anyhow::Result<()> {
|
||||||
config::validate_config(conf).die_with(|error| format!("Invalid config: {}", error));
|
config::validate_config(conf).die_with(|error| format!("Invalid config: {}", error));
|
||||||
println!("Finding out the IP address...");
|
println!("Finding out the IP address...");
|
||||||
let ipv4_result = IP::get_ipv4().await;
|
let (ipv4_result, ipv6_result) = join!(ip_source.get_ipv4(), ip_source.get_ipv6());
|
||||||
let ipv6_result = IP::get_ipv6().await;
|
|
||||||
let ipv4 = ipv4_result.as_ref();
|
let ipv4 = ipv4_result.as_ref();
|
||||||
let ipv6 = ipv6_result.as_ref();
|
let ipv6 = ipv6_result.as_ref();
|
||||||
println!("Found these:");
|
println!("Found these:");
|
||||||
|
@ -136,10 +136,11 @@ async fn main() -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_dispatch(conf: &Config) -> anyhow::Result<()> {
|
async fn run_dispatch(conf: &Config) -> anyhow::Result<()> {
|
||||||
match conf.ip_source {
|
let ip_source: Box<dyn IPSource> = match conf.ip_source {
|
||||||
IPSourceName::Ipify => run::<IPSourceIpify>("https://api.gandi.net", conf).await,
|
IPSourceName::Ipify => Box::new(IPSourceIpify),
|
||||||
IPSourceName::Icanhazip => run::<IPSourceIcanhazip>("https://api.gandi.net", conf).await,
|
IPSourceName::Icanhazip => Box::new(IPSourceIcanhazip),
|
||||||
}
|
};
|
||||||
|
run("https://api.gandi.net", &ip_source, conf).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -151,14 +152,14 @@ mod tests {
|
||||||
use httpmock::MockServer;
|
use httpmock::MockServer;
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
struct IPSourceMock {}
|
struct IPSourceMock;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl IPSource for IPSourceMock {
|
impl IPSource for IPSourceMock {
|
||||||
async fn get_ipv4() -> anyhow::Result<String> {
|
async fn get_ipv4(&self) -> anyhow::Result<String> {
|
||||||
Ok("192.168.0.0".to_string())
|
Ok("192.168.0.0".to_string())
|
||||||
}
|
}
|
||||||
async fn get_ipv6() -> anyhow::Result<String> {
|
async fn get_ipv6(&self) -> anyhow::Result<String> {
|
||||||
Ok("fe80:0000:0208:74ff:feda:625c".to_string())
|
Ok("fe80:0000:0208:74ff:feda:625c".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +195,8 @@ mod tests {
|
||||||
..Opts::default()
|
..Opts::default()
|
||||||
};
|
};
|
||||||
let conf = config::load_config(&opts).expect("Failed to load config");
|
let conf = config::load_config(&opts).expect("Failed to load config");
|
||||||
run::<IPSourceMock>(server.base_url().as_str(), &conf)
|
let ip_source: Box<dyn IPSource> = Box::new(IPSourceMock);
|
||||||
|
run(server.base_url().as_str(), &ip_source, &conf)
|
||||||
.await
|
.await
|
||||||
.expect("Failed when running the update");
|
.expect("Failed when running the update");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue