From 98cb9ddaae405f1f9842470d27d4c4938da0db6a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 23 Feb 2024 13:21:07 +0100 Subject: [PATCH] add a Client image --- packages/dns-test/src/client.rs | 6 +- packages/dns-test/src/container.rs | 80 ++++++++++++++++--- packages/dns-test/src/container/network.rs | 4 +- .../dns-test/src/docker/client.Dockerfile | 8 ++ .../dns-test/src/docker/unbound.Dockerfile | 4 - packages/dns-test/src/lib.rs | 35 -------- packages/dns-test/src/name_server.rs | 3 +- packages/dns-test/src/resolver.rs | 3 +- 8 files changed, 85 insertions(+), 58 deletions(-) create mode 100644 packages/dns-test/src/docker/client.Dockerfile diff --git a/packages/dns-test/src/client.rs b/packages/dns-test/src/client.rs index b66b73ca..af6861b5 100644 --- a/packages/dns-test/src/client.rs +++ b/packages/dns-test/src/client.rs @@ -1,10 +1,10 @@ use core::str::FromStr; use std::net::Ipv4Addr; -use crate::container::{Container, Network}; +use crate::container::{Container, Image, Network}; use crate::record::{Record, RecordType}; use crate::trust_anchor::TrustAnchor; -use crate::{Error, Implementation, Result, FQDN}; +use crate::{Error, Result, FQDN}; pub struct Client { inner: Container, @@ -13,7 +13,7 @@ pub struct Client { impl Client { pub fn new(network: &Network) -> Result { Ok(Self { - inner: Container::run(&Implementation::Unbound, network)?, + inner: Container::run(&Image::Client, network)?, }) } diff --git a/packages/dns-test/src/container.rs b/packages/dns-test/src/container.rs index 92550114..d3651d93 100644 --- a/packages/dns-test/src/container.rs +++ b/packages/dns-test/src/container.rs @@ -1,17 +1,17 @@ mod network; -use core::str; +use core::{fmt, str}; use std::net::Ipv4Addr; use std::process::{self, ChildStdout, ExitStatus}; use std::process::{Command, Stdio}; use std::sync::atomic::AtomicUsize; -use std::sync::{atomic, Arc}; +use std::sync::{atomic, Arc, Once}; use std::{env, fs}; use tempfile::{NamedTempFile, TempDir}; pub use crate::container::network::Network; -use crate::{Error, Implementation, Result}; +use crate::{Error, Implementation, Repository, Result}; #[derive(Clone)] pub struct Container { @@ -20,16 +20,72 @@ pub struct Container { const PACKAGE_NAME: &str = env!("CARGO_PKG_NAME"); +#[derive(Clone)] +pub enum Image { + Client, + Hickory(Repository<'static>), + Unbound, +} + +impl Image { + fn dockerfile(&self) -> &'static str { + match self { + Self::Unbound => include_str!("docker/unbound.Dockerfile"), + Self::Hickory { .. } => include_str!("docker/hickory.Dockerfile"), + Self::Client => include_str!("docker/client.Dockerfile"), + } + } + + fn once(&self) -> &'static Once { + match self { + Self::Client { .. } => { + static CLIENT_ONCE: Once = Once::new(); + &CLIENT_ONCE + } + + Self::Hickory { .. } => { + static HICKORY_ONCE: Once = Once::new(); + &HICKORY_ONCE + } + + Self::Unbound { .. } => { + static UNBOUND_ONCE: Once = Once::new(); + &UNBOUND_ONCE + } + } + } +} + +impl From for Image { + fn from(implementation: Implementation) -> Self { + match implementation { + Implementation::Unbound => Self::Unbound, + Implementation::Hickory(repo) => Self::Hickory(repo), + } + } +} + +impl fmt::Display for Image { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + Self::Client => "client", + Self::Hickory { .. } => "hickory", + Self::Unbound => "unbound", + }; + f.write_str(s) + } +} + impl Container { /// Starts the container in a "parked" state - pub fn run(implementation: &Implementation, network: &Network) -> Result { + pub fn run(image: &Image, network: &Network) -> Result { // TODO make this configurable and support hickory & bind - let dockerfile = implementation.dockerfile(); + let dockerfile = image.dockerfile(); let docker_build_dir = TempDir::new()?; let docker_build_dir = docker_build_dir.path(); fs::write(docker_build_dir.join("Dockerfile"), dockerfile)?; - let image_tag = format!("{PACKAGE_NAME}-{implementation}"); + let image_tag = format!("{PACKAGE_NAME}-{image}"); let mut command = Command::new("docker"); command @@ -37,13 +93,13 @@ impl Container { .arg(&image_tag) .arg(docker_build_dir); - let repo = if let Implementation::Hickory(repo) = implementation { + let repo = if let Image::Hickory(repo) = image { Some(repo) } else { None }; - implementation.once().call_once(|| { + image.once().call_once(|| { if let Some(repo) = repo { let mut cp_r = Command::new("git"); cp_r.args([ @@ -66,7 +122,7 @@ impl Container { let mut command = Command::new("docker"); let pid = process::id(); let count = container_count(); - let name = format!("{PACKAGE_NAME}-{implementation}-{pid}-{count}"); + let name = format!("{PACKAGE_NAME}-{image}-{pid}-{count}"); command .args([ "run", @@ -334,7 +390,7 @@ mod tests { #[test] fn run_works() -> Result<()> { let network = Network::new()?; - let container = Container::run(&Implementation::Unbound, &network)?; + let container = Container::run(&Image::Client, &network)?; let output = container.output(&["true"])?; assert!(output.status.success()); @@ -345,7 +401,7 @@ mod tests { #[test] fn ipv4_addr_works() -> Result<()> { let network = Network::new()?; - let container = Container::run(&Implementation::Unbound, &network)?; + let container = Container::run(&Image::Client, &network)?; let ipv4_addr = container.ipv4_addr(); let output = container.output(&["ping", "-c1", &format!("{ipv4_addr}")])?; @@ -357,7 +413,7 @@ mod tests { #[test] fn cp_works() -> Result<()> { let network = Network::new()?; - let container = Container::run(&Implementation::Unbound, &network)?; + let container = Container::run(&Image::Client, &network)?; let path = "/tmp/somefile"; let contents = "hello"; diff --git a/packages/dns-test/src/container/network.rs b/packages/dns-test/src/container/network.rs index 7e9f81b1..6c1751ca 100644 --- a/packages/dns-test/src/container/network.rs +++ b/packages/dns-test/src/container/network.rs @@ -113,7 +113,7 @@ fn network_count() -> usize { #[cfg(test)] mod tests { - use crate::{container::Container, Implementation}; + use crate::container::{Container, Image}; use super::*; @@ -146,7 +146,7 @@ mod tests { let network = Network::new().expect("Failed to create network"); let network_name = network.name().to_string(); let container = - Container::run(&Implementation::Unbound, &network).expect("Failed to start container"); + Container::run(&Image::Client, &network).expect("Failed to start container"); assert!(exists_network(&network_name)); drop(network); diff --git a/packages/dns-test/src/docker/client.Dockerfile b/packages/dns-test/src/docker/client.Dockerfile new file mode 100644 index 00000000..9ab60a70 --- /dev/null +++ b/packages/dns-test/src/docker/client.Dockerfile @@ -0,0 +1,8 @@ +FROM debian:bookworm-slim + +# dnsutils = dig & delv +# iputils-ping = ping +RUN apt-get update && \ + apt-get install -y \ + dnsutils \ + iputils-ping diff --git a/packages/dns-test/src/docker/unbound.Dockerfile b/packages/dns-test/src/docker/unbound.Dockerfile index b42777ef..4b8139f0 100644 --- a/packages/dns-test/src/docker/unbound.Dockerfile +++ b/packages/dns-test/src/docker/unbound.Dockerfile @@ -1,12 +1,8 @@ FROM debian:bookworm-slim -# dnsutils = dig & delv -# iputils-ping = ping # ldns-utils = ldns-{key2ds,keygen,signzone} RUN apt-get update && \ apt-get install -y \ - dnsutils \ - iputils-ping \ ldnsutils \ nsd \ tshark \ diff --git a/packages/dns-test/src/lib.rs b/packages/dns-test/src/lib.rs index 8c06730c..4f8b5c01 100644 --- a/packages/dns-test/src/lib.rs +++ b/packages/dns-test/src/lib.rs @@ -1,9 +1,7 @@ //! A test framework for all things DNS -use core::fmt; use std::borrow::Cow; use std::path::Path; -use std::sync::Once; use url::Url; @@ -57,45 +55,12 @@ pub fn Repository(input: impl Into>) -> Repository<'static> { Repository { inner: input } } -impl Implementation { - fn dockerfile(&self) -> &'static str { - match self { - Implementation::Unbound => include_str!("docker/unbound.Dockerfile"), - Implementation::Hickory { .. } => include_str!("docker/hickory.Dockerfile"), - } - } - - fn once(&self) -> &'static Once { - match self { - Implementation::Unbound => { - static UNBOUND_ONCE: Once = Once::new(); - &UNBOUND_ONCE - } - - Implementation::Hickory { .. } => { - static HICKORY_ONCE: Once = Once::new(); - &HICKORY_ONCE - } - } - } -} - impl Default for Implementation { fn default() -> Self { Self::Unbound } } -impl fmt::Display for Implementation { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match self { - Implementation::Unbound => "unbound", - Implementation::Hickory { .. } => "hickory", - }; - f.write_str(s) - } -} - pub fn subject() -> Implementation { if let Ok(subject) = std::env::var("DNS_TEST_SUBJECT") { if subject == "unbound" { diff --git a/packages/dns-test/src/name_server.rs b/packages/dns-test/src/name_server.rs index 7cc942b0..724a4499 100644 --- a/packages/dns-test/src/name_server.rs +++ b/packages/dns-test/src/name_server.rs @@ -47,8 +47,9 @@ impl<'a> NameServer<'a, Stopped> { nameserver: nameserver.clone(), }); + let image = implementation.into(); Ok(Self { - container: Container::run(&Implementation::Unbound, network)?, + container: Container::run(&image, network)?, zone_file, state: Stopped, }) diff --git a/packages/dns-test/src/resolver.rs b/packages/dns-test/src/resolver.rs index b8d59c22..948f41f9 100644 --- a/packages/dns-test/src/resolver.rs +++ b/packages/dns-test/src/resolver.rs @@ -33,7 +33,8 @@ impl Resolver { "must configure at least one local root server" ); - let container = Container::run(&implementation, network)?; + let image = implementation.clone().into(); + let container = Container::run(&image, network)?; let mut hints = String::new(); for root in roots {