source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
[[package]]
name = "bitflags"
version = "1.3.2"
[[package]]
name = "bumpalo"
-version = "3.11.1"
+version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytes"
[[package]]
name = "cc"
-version = "1.0.77"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cfg-if"
[[package]]
name = "either"
-version = "1.8.0"
+version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "encoding_rs"
[[package]]
name = "hermit-abi"
-version = "0.1.19"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "ipnet"
-version = "2.7.0"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
+checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
[[package]]
name = "itertools"
[[package]]
name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "js-sys"
[[package]]
name = "libc"
-version = "0.2.138"
+version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "log"
"libc",
"log",
"wasi",
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
[[package]]
name = "num_cpus"
-version = "1.14.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
[[package]]
name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "openssl"
-version = "0.10.44"
+version = "0.10.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29d971fd5722fec23977260f6e81aa67d2f22cadbdc2aa049f1022d9a3be1566"
+checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
dependencies = [
"bitflags",
"cfg-if",
[[package]]
name = "openssl-sys"
-version = "0.9.79"
+version = "0.9.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5454462c0eced1e97f2ec09036abc8da362e66802f66fd20f86854d9d8cbcbc4"
+checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
dependencies = [
"autocfg",
"cc",
[[package]]
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "reqwest"
-version = "0.11.13"
+version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
+checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
dependencies = [
- "base64",
+ "base64 0.21.0",
"bytes",
"encoding_rs",
"futures-core",
[[package]]
name = "ron"
- version = "0.6.6"
+ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
- checksum = "86018df177b1beef6c7c8ef949969c4f7cb9a9344181b92486b23c79995bdaa4"
+ checksum = "300a51053b1cb55c80b7a9fde4120726ddf25ca241a1cbb926626f62fb136bff"
dependencies = [
- "base64",
+ "base64 0.13.1",
"bitflags",
"serde",
]
[[package]]
name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "schannel"
-version = "0.1.20"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
+checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
dependencies = [
- "lazy_static",
- "windows-sys 0.36.1",
+ "windows-sys",
]
[[package]]
name = "security-framework"
-version = "2.7.0"
+version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
+checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721"
dependencies = [
"bitflags",
"core-foundation",
[[package]]
name = "security-framework-sys"
-version = "2.6.1"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
+checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc",
[[package]]
name = "serde"
-version = "1.0.150"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.150"
+version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "serde_json"
-version = "1.0.89"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
[[package]]
name = "syn"
-version = "1.0.105"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
[[package]]
name = "tokio"
-version = "1.23.0"
+version = "1.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
+checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb"
dependencies = [
"autocfg",
"bytes",
"num_cpus",
"pin-project-lite",
"socket2",
- "windows-sys 0.42.0",
+ "windows-sys",
]
[[package]]
[[package]]
name = "try-lock"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-bidi"
-version = "0.3.8"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-normalization"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-[[package]]
-name = "windows-sys"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
-dependencies = [
- "windows_aarch64_msvc 0.36.1",
- "windows_i686_gnu 0.36.1",
- "windows_i686_msvc 0.36.1",
- "windows_x86_64_gnu 0.36.1",
- "windows_x86_64_msvc 0.36.1",
-]
-
[[package]]
name = "windows-sys"
version = "0.42.0"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
- "windows_aarch64_msvc 0.42.0",
- "windows_i686_gnu 0.42.0",
- "windows_i686_msvc 0.42.0",
- "windows_x86_64_gnu 0.42.0",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
"windows_x86_64_gnullvm",
- "windows_x86_64_msvc 0.42.0",
+ "windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.36.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.0"
+version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
[[package]]
name = "winreg"
/*
* API Reference: https://api.gandi.net/docs/livedns/
+ *
* Some similar implementations:
* - https://github.com/rmarchant/gandi-ddns/blob/master/gandi_ddns.py
* - https://github.com/brianhp2/gandi-automatic-dns
*
- * TODO:
- * - Log to stdout with (at least) timestamps.
- * - Renew function.
*/
#![cfg_attr(debug_assertions, allow(unused_variables, unused_imports, dead_code))]
- use std::{ fs::File, net::{ IpAddr, Ipv4Addr }, thread, time };
- use ron::{ de::from_reader, ser::to_writer };
- use serde::{ Deserialize, Serialize };
- use serde_json::{ Value, json };
+ use std::{
+ net::{IpAddr, Ipv4Addr},
+ thread, time,
+ };
- // A generic result of type 'T'.
- type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
+ use serde_json::{json, Value};
- #[derive(Debug)]
- struct Error {
- message: String
- }
+ use crate::{
+ config::Config,
+ error::{Error, Result},
+ };
- impl std::fmt::Display for Error {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "Error: {}", &self.message)
- }
- }
-
- impl std::error::Error for Error { }
-
- #[derive(Debug, Clone, Deserialize, Serialize)]
- struct Config {
- delay_between_check: time::Duration,
- api_key: String,
- fqdn: String,
- domains: Vec<String>,
- ttl: i32
- }
-
- impl Config {
- fn default() -> Self {
- Config { delay_between_check: time::Duration::from_secs(120), api_key: String::from(""), fqdn: String::from(""), domains: Vec::new(), ttl: 300 }
- }
-
- fn read(file_path: &str) -> Result<Config> {
- match File::open(file_path) {
- Ok(file) => from_reader(file).map_err(|e| e.into()),
- // The file doesn't exit -> create it with default values.
- Err(_) => {
- let file = File::create(file_path)?;
- let default_config = Config::default();
- to_writer(file, &default_config)?;
- Ok(default_config)
- }
- }
- }
- }
+ mod config;
+ mod error;
const FILE_CONF: &str = "config.ron";
fn main() -> Result<()> {
- println!("=== GANDI LiveDNS updater ===");
+ println!("GANDI LiveDNS updater");
let config = Config::read(FILE_CONF)?;
- println!("Configuration: {:?}", Config { api_key: String::from("*****"), ..config.clone() });
+ println!(
+ "Configuration: {:?}",
+ Config {
+ api_key: String::from("*****"),
+ ..config.clone()
+ }
+ );
loop {
let time_beginning_loop = time::Instant::now();
- if let Err(err) = check_and_update_dns(&config.api_key, &config.fqdn, &config.domains, config.ttl) {
- println!("!! Error: {}", err);
+ if let Err(err) = check_and_update_dns(&config.api_key, &config.domains, config.ttl) {
+ println!("!! {}", err);
}
let elapsed = time::Instant::now() - time_beginning_loop;
}
}
- fn check_and_update_dns(api_key: &str, fqdn: &str, domains: &Vec<String>, ttl: i32) -> Result<()> {
+ fn check_and_update_dns(api_key: &str, domains: &Vec<(String, String)>, ttl: i32) -> Result<()> {
let real_ip = get_real_ip()?;
- for domain in domains {
- let current_ip = get_current_record_ip(api_key, domain, fqdn)?;
+ for (hostname, domain) in domains {
+ let current_ip = get_current_record_ip(api_key, hostname, domain)?;
if real_ip != current_ip {
- println!("IP addresses don't match for domain {}: real = {}, dns = {}. Renewing DNS...", domain, real_ip, current_ip);
- update_record_ip(api_key, domain, fqdn, real_ip, ttl)?;
- println!("Renewing of {} successfully", domain);
+ println!(
+ "IP addresses don't match for domain {}: real = {}, dns = {}. Renewing DNS...",
+ domain, real_ip, current_ip
+ );
+ update_record_ip(api_key, hostname, domain, real_ip, ttl)?;
+ println!("Renewing of {}.{} successfully", hostname, domain);
}
}
}
fn get_real_ip() -> Result<Ipv4Addr> {
-
let url = "https://api.ipify.org";
let client = reqwest::blocking::Client::new();
match client.get(url).send() {
- Ok(resp) =>
+ Ok(resp) => {
if resp.status().is_success() {
let content = resp.text().unwrap();
- match content.parse::<IpAddr>() {
+ match content.parse() {
Ok(IpAddr::V4(ip_v4)) => Ok(ip_v4),
- _ => Err(Box::new(Error { message: String::from("Can't parse IPv4 from ipify") }))
+ _ => Err(Box::new(Error {
+ message: String::from("Can't parse IPv4 from ipify"),
+ })),
}
} else {
- Err(Box::new(Error { message: format!("Request unsuccessful: {:#?}", resp) }))
- },
-
- Err(error) => {
- Err(Box::new(Error { message: format!("Error during request: {:?}", error) }))
+ Err(Box::new(Error {
+ message: format!("Request unsuccessful to {}: {:#?}", url, resp),
+ }))
+ }
}
+ Err(error) => Err(Box::new(Error {
+ message: format!("Error during request to {}: {:?}", url, error),
+ })),
+ }
+ }
+
+ fn get_current_record_ip(api_key: &str, name: &str, fqdn: &str) -> Result<Ipv4Addr> {
+ let json_value = request_livedns_gandi(
+ api_key,
+ &format!("domains/{}/records/{}/A", fqdn, name),
+ Method::Get,
+ )?;
+
+ match &json_value["rrset_values"][0] {
+ Value::String(ip_str) => Ok(ip_str.parse()?),
+ _ => Result::Err(Box::new(Error {
+ message: format!(
+ "Unable to extract the IP from the JSON answer: {}",
+ json_value
+ ),
+ })),
}
}
+ fn update_record_ip(api_key: &str, name: &str, fqdn: &str, ip: Ipv4Addr, ttl: i32) -> Result<()> {
+ let json_body = json!(
+ {
+ "rrset_values": [ format!("{}", ip) ],
+ "rrset_ttl": ttl
+ }
+ );
+
+ let json_value = request_livedns_gandi(
+ api_key,
+ &format!("domains/{}/records/{}/A", fqdn, name),
+ Method::Put(json_body.to_string()),
+ )?;
+
+ println!("Update response: {}", json_value);
+
+ Ok(())
+ }
+
enum Method {
Put(String),
- Get
+ Get,
}
fn request_livedns_gandi(api_key: &str, url_fragment: &str, method: Method) -> Result<Value> {
let url = format!("https://api.gandi.net/v5/livedns/{}", url_fragment);
let client = reqwest::blocking::Client::new();
- let request_builder =
- match method {
- Method::Put(body) => client.put(url).body(body),
- Method::Get => client.get(url)
- };
+ let request_builder = match method {
+ Method::Put(body) => client.put(&url).body(body),
+ Method::Get => client.get(&url),
+ };
- match request_builder.header("Authorization", format!("Apikey {}", api_key)).send() {
- Ok(resp) =>
+ match request_builder
+ .header("Authorization", format!("Apikey {}", api_key))
+ .send()
+ {
+ Ok(resp) => {
if resp.status().is_success() {
let content = resp.text().unwrap();
Ok(serde_json::from_str(&content).unwrap())
} else {
- Err(Box::new(Error { message: format!("Request unsuccessful: {:#?}", resp) }))
- },
- Err(error) =>
- Err(Box::new(Error { message: format!("Error during request: {:?}", error) }))
- }
- }
-
- fn get_current_record_ip(api_key: &str, name: &str, fqdn: &str) -> Result<Ipv4Addr> {
- let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Get)?;
-
- match &json_value["rrset_values"][0] {
- Value::String(ip_str) =>
- Ok(ip_str.parse()?),
- _ =>
- Result::Err(Box::new(Error { message: format!("Unable to extract the IP from the JSON answer: {}", json_value) }))
- }
- }
-
- fn update_record_ip(api_key: &str, name: &str, fqdn: &str, ip: Ipv4Addr, ttl: i32) -> Result<()> {
- let json_body =
- json!(
- {
- "rrset_values": [ format!("{}", ip) ],
- "rrset_ttl": ttl
+ Err(Box::new(Error {
+ message: format!("Request unsuccessful to {}: {:#?}", &url, resp),
+ }))
}
- );
-
- let json_value = request_livedns_gandi(api_key, &format!("domains/{}/records/{}/A", fqdn, name), Method::Put(json_body.to_string()))?;
-
- println!("Update response: {}", json_value);
-
- Ok(())
+ }
+ Err(error) => Err(Box::new(Error {
+ message: format!("Error during request to {}: {:?}", &url, error),
+ })),
+ }
}