use Ipv4Addr type for IP addresses
This commit is contained in:
parent
d79581bdcc
commit
c7e0580c7a
@ -1,4 +1,4 @@
|
|||||||
use std::process::Child;
|
use std::{net::Ipv4Addr, process::Child};
|
||||||
|
|
||||||
use minijinja::{context, Environment};
|
use minijinja::{context, Environment};
|
||||||
|
|
||||||
@ -34,8 +34,8 @@ impl AuthoritativeNameServer {
|
|||||||
Ok(Self { child, container })
|
Ok(Self { child, container })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ip_addr(&self) -> Result<String> {
|
pub fn ipv4_addr(&self) -> Ipv4Addr {
|
||||||
self.container.ip_addr()
|
self.container.ipv4_addr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn tld_setup() -> Result<()> {
|
fn tld_setup() -> Result<()> {
|
||||||
let tld_ns = AuthoritativeNameServer::start(Domain::Tld { domain: "com." })?;
|
let tld_ns = AuthoritativeNameServer::start(Domain::Tld { domain: "com." })?;
|
||||||
let ip_addr = tld_ns.ip_addr()?;
|
let ip_addr = tld_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Container::run()?;
|
let client = Container::run()?;
|
||||||
let output = client.exec(&["dig", &format!("@{ip_addr}"), "SOA", "com."])?;
|
let output = client.exec(&["dig", &format!("@{ip_addr}"), "SOA", "com."])?;
|
||||||
@ -100,7 +100,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn root_setup() -> Result<()> {
|
fn root_setup() -> Result<()> {
|
||||||
let root_ns = AuthoritativeNameServer::start(Domain::Root)?;
|
let root_ns = AuthoritativeNameServer::start(Domain::Root)?;
|
||||||
let ip_addr = root_ns.ip_addr()?;
|
let ip_addr = root_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Container::run()?;
|
let client = Container::run()?;
|
||||||
let output = client.exec(&["dig", &format!("@{ip_addr}"), "SOA", "."])?;
|
let output = client.exec(&["dig", &format!("@{ip_addr}"), "SOA", "."])?;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use core::str;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::net::Ipv4Addr;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{self, Child, Output};
|
use std::process::{self, Child, Output};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
@ -10,8 +12,10 @@ use tempfile::NamedTempFile;
|
|||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
pub struct Container {
|
pub struct Container {
|
||||||
id: String,
|
|
||||||
_name: String,
|
_name: String,
|
||||||
|
id: String,
|
||||||
|
// TODO probably also want the IPv6 address
|
||||||
|
ipv4_addr: Ipv4Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Container {
|
impl Container {
|
||||||
@ -61,15 +65,16 @@ impl Container {
|
|||||||
return Err(format!("`{command:?}` failed").into());
|
return Err(format!("`{command:?}` failed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = core::str::from_utf8(&output.stdout)?.trim().to_string();
|
let id = str::from_utf8(&output.stdout)?.trim().to_string();
|
||||||
dbg!(&id);
|
dbg!(&id);
|
||||||
let container = Self {
|
|
||||||
|
let ipv4_addr = get_ipv4_addr(&id)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
id,
|
id,
|
||||||
_name: container_name,
|
_name: container_name,
|
||||||
};
|
ipv4_addr,
|
||||||
dbg!(container.ip_addr()?);
|
})
|
||||||
|
|
||||||
Ok(container)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp(&self, path_in_container: &str, file_contents: &str, chmod: &str) -> Result<()> {
|
pub fn cp(&self, path_in_container: &str, file_contents: &str, chmod: &str) -> Result<()> {
|
||||||
@ -114,29 +119,33 @@ impl Container {
|
|||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cache this to avoid calling `docker inspect` every time
|
pub fn ipv4_addr(&self) -> Ipv4Addr {
|
||||||
pub fn ip_addr(&self) -> Result<String> {
|
self.ipv4_addr
|
||||||
let mut command = Command::new("docker");
|
|
||||||
command
|
|
||||||
.args([
|
|
||||||
"inspect",
|
|
||||||
"-f",
|
|
||||||
"{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}",
|
|
||||||
])
|
|
||||||
.arg(&self.id);
|
|
||||||
|
|
||||||
let output = command.output()?;
|
|
||||||
if !output.status.success() {
|
|
||||||
return Err(format!("`{command:?}` failed").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let ip_addr = core::str::from_utf8(&output.stdout)?.trim().to_string();
|
|
||||||
dbg!(&ip_addr);
|
|
||||||
|
|
||||||
Ok(ip_addr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO cache this to avoid calling `docker inspect` every time
|
||||||
|
fn get_ipv4_addr(container_id: &str) -> Result<Ipv4Addr> {
|
||||||
|
let mut command = Command::new("docker");
|
||||||
|
command
|
||||||
|
.args([
|
||||||
|
"inspect",
|
||||||
|
"-f",
|
||||||
|
"{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}",
|
||||||
|
])
|
||||||
|
.arg(container_id);
|
||||||
|
|
||||||
|
let output = command.output()?;
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(format!("`{command:?}` failed").into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let ipv4_addr = str::from_utf8(&output.stdout)?.trim().to_string();
|
||||||
|
dbg!(&ipv4_addr);
|
||||||
|
|
||||||
|
Ok(ipv4_addr.parse()?)
|
||||||
|
}
|
||||||
|
|
||||||
// ensure the container gets deleted
|
// ensure the container gets deleted
|
||||||
impl Drop for Container {
|
impl Drop for Container {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
@ -152,8 +161,6 @@ impl Drop for Container {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::net::Ipv4Addr;
|
|
||||||
|
|
||||||
use crate::CHMOD_RW_EVERYONE;
|
use crate::CHMOD_RW_EVERYONE;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -169,11 +176,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ip_addr_works() -> Result<()> {
|
fn ipv4_addr_works() -> Result<()> {
|
||||||
let container = Container::run()?;
|
let container = Container::run()?;
|
||||||
|
let ipv4_addr = container.ipv4_addr();
|
||||||
|
|
||||||
let ip_addr = container.ip_addr()?;
|
let output = container.exec(&["ping", "-c1", &format!("{ipv4_addr}")])?;
|
||||||
assert!(ip_addr.parse::<Ipv4Addr>().is_ok());
|
assert!(output.status.success());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::net::Ipv4Addr;
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -13,7 +14,7 @@ pub struct RecursiveResolver {
|
|||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct RootServer {
|
pub struct RootServer {
|
||||||
name: String,
|
name: String,
|
||||||
ip_addr: String,
|
ip_addr: Ipv4Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root_hints(roots: &[RootServer]) -> String {
|
fn root_hints(roots: &[RootServer]) -> String {
|
||||||
@ -38,8 +39,8 @@ impl RecursiveResolver {
|
|||||||
Ok(Self { child, container })
|
Ok(Self { child, container })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ip_addr(&self) -> Result<String> {
|
pub fn ipv4_addr(&self) -> Ipv4Addr {
|
||||||
self.container.ip_addr()
|
self.container.ipv4_addr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,14 +57,15 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore = "FIXME"]
|
||||||
fn can_resolve() -> Result<()> {
|
fn can_resolve() -> Result<()> {
|
||||||
let root_ns = AuthoritativeNameServer::start(crate::Domain::Root)?;
|
let root_ns = AuthoritativeNameServer::start(crate::Domain::Root)?;
|
||||||
let roots = &[RootServer {
|
let roots = &[RootServer {
|
||||||
name: "my.root-server.com".to_string(),
|
name: "my.root-server.com".to_string(),
|
||||||
ip_addr: root_ns.ip_addr()?,
|
ip_addr: root_ns.ipv4_addr(),
|
||||||
}];
|
}];
|
||||||
let resolver = RecursiveResolver::start(roots)?;
|
let resolver = RecursiveResolver::start(roots)?;
|
||||||
let resolver_ip_addr = resolver.ip_addr()?;
|
let resolver_ip_addr = resolver.ipv4_addr();
|
||||||
|
|
||||||
let container = Container::run()?;
|
let container = Container::run()?;
|
||||||
let output = container.exec(&["dig", &format!("@{}", resolver_ip_addr), "example.com"])?;
|
let output = container.exec(&["dig", &format!("@{}", resolver_ip_addr), "example.com"])?;
|
||||||
@ -77,15 +79,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn root_hints_template_works() {
|
fn root_hints_template_works() {
|
||||||
let expected = [
|
let expected = [
|
||||||
("a.root-server.com", "172.17.0.1"),
|
("a.root-server.com", Ipv4Addr::new(172, 17, 0, 1)),
|
||||||
("b.root-server.com", "172.17.0.2"),
|
("b.root-server.com", Ipv4Addr::new(172, 17, 0, 2)),
|
||||||
];
|
];
|
||||||
|
|
||||||
let roots = expected
|
let roots = expected
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(ns_name, ip_addr)| RootServer {
|
.map(|(ns_name, ip_addr)| RootServer {
|
||||||
name: ns_name.to_string(),
|
name: ns_name.to_string(),
|
||||||
ip_addr: ip_addr.to_string(),
|
ip_addr: *ip_addr,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -117,7 +119,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(expected_ns_name, ns_name);
|
assert_eq!(expected_ns_name, ns_name);
|
||||||
assert_eq!("A", record_type);
|
assert_eq!("A", record_type);
|
||||||
assert_eq!(expected_ip_addr, ip_addr);
|
assert_eq!(expected_ip_addr.to_string(), ip_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user