Skip to content
This repository has been archived by the owner on Jun 7, 2024. It is now read-only.

Commit

Permalink
add a Client image
Browse files Browse the repository at this point in the history
  • Loading branch information
japaric committed Feb 23, 2024
1 parent c0b681e commit 98cb9dd
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 58 deletions.
6 changes: 3 additions & 3 deletions packages/dns-test/src/client.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -13,7 +13,7 @@ pub struct Client {
impl Client {
pub fn new(network: &Network) -> Result<Self> {
Ok(Self {
inner: Container::run(&Implementation::Unbound, network)?,
inner: Container::run(&Image::Client, network)?,
})
}

Expand Down
80 changes: 68 additions & 12 deletions packages/dns-test/src/container.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -20,30 +20,86 @@ 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<Implementation> 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<Self> {
pub fn run(image: &Image, network: &Network) -> Result<Self> {
// 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
.args(["build", "-t"])
.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([
Expand All @@ -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",
Expand Down Expand Up @@ -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());
Expand All @@ -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}")])?;
Expand All @@ -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";
Expand Down
4 changes: 2 additions & 2 deletions packages/dns-test/src/container/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ fn network_count() -> usize {

#[cfg(test)]
mod tests {
use crate::{container::Container, Implementation};
use crate::container::{Container, Image};

use super::*;

Expand Down Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions packages/dns-test/src/docker/client.Dockerfile
Original file line number Diff line number Diff line change
@@ -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
4 changes: 0 additions & 4 deletions packages/dns-test/src/docker/unbound.Dockerfile
Original file line number Diff line number Diff line change
@@ -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 \
Expand Down
35 changes: 0 additions & 35 deletions packages/dns-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -57,45 +55,12 @@ pub fn Repository(input: impl Into<Cow<'static, str>>) -> 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" {
Expand Down
3 changes: 2 additions & 1 deletion packages/dns-test/src/name_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
Expand Down
3 changes: 2 additions & 1 deletion packages/dns-test/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 98cb9dd

Please sign in to comment.