build hickory from a local/remote git source

DNS_TEST_SUBJECT now needs to contain the URL to the hickory source code
This commit is contained in:
Jorge Aparicio 2024-02-16 13:40:07 +01:00
parent 0e2b35699c
commit 55184172e3
7 changed files with 51 additions and 20 deletions

View File

@ -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(&Implementation::Unbound, network)?,
})
}

View File

@ -22,7 +22,7 @@ const PACKAGE_NAME: &str = env!("CARGO_PKG_NAME");
impl Container {
/// Starts the container in a "parked" state
pub fn run(implementation: Implementation, network: &Network) -> Result<Self> {
pub fn run(implementation: &Implementation, network: &Network) -> Result<Self> {
// TODO make this configurable and support hickory & bind
let dockerfile = implementation.dockerfile();
let docker_build_dir = TempDir::new()?;
@ -37,7 +37,26 @@ impl Container {
.arg(&image_tag)
.arg(docker_build_dir);
let srcdir = if let Implementation::Hickory { url } = implementation {
Some(url)
} else {
None
};
implementation.once().call_once(|| {
if let Some(srcdir) = srcdir {
let mut cp_r = Command::new("git");
cp_r.args([
"clone",
"--depth",
"1",
srcdir,
&docker_build_dir.join("src").display().to_string(),
]);
exec_or_panic(&mut cp_r, false);
}
exec_or_panic(&mut command, verbose_docker_build());
});
@ -312,7 +331,7 @@ mod tests {
#[test]
fn run_works() -> Result<()> {
let network = Network::new()?;
let container = Container::run(Implementation::Unbound, &network)?;
let container = Container::run(&Implementation::Unbound, &network)?;
let output = container.output(&["true"])?;
assert!(output.status.success());
@ -323,7 +342,7 @@ mod tests {
#[test]
fn ipv4_addr_works() -> Result<()> {
let network = Network::new()?;
let container = Container::run(Implementation::Unbound, &network)?;
let container = Container::run(&Implementation::Unbound, &network)?;
let ipv4_addr = container.ipv4_addr();
let output = container.output(&["ping", "-c1", &format!("{ipv4_addr}")])?;
@ -335,7 +354,7 @@ mod tests {
#[test]
fn cp_works() -> Result<()> {
let network = Network::new()?;
let container = Container::run(Implementation::Unbound, &network)?;
let container = Container::run(&Implementation::Unbound, &network)?;
let path = "/tmp/somefile";
let contents = "hello";

View File

@ -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(&Implementation::Unbound, &network).expect("Failed to start container");
assert!(exists_network(&network_name));
drop(network);

View File

@ -4,5 +4,6 @@ RUN apt-get update && \
apt-get install -y \
tshark
RUN cargo install hickory-dns --version 0.24.0 --features recursor --debug
COPY ./src /usr/src/hickory
RUN cargo install --path /usr/src/hickory/bin --features recursor --debug
env RUST_LOG=debug

View File

@ -21,17 +21,17 @@ mod trust_anchor;
pub mod tshark;
pub mod zone_file;
#[derive(Clone, Copy)]
#[derive(Clone)]
pub enum Implementation {
Unbound,
Hickory,
Hickory { url: String },
}
impl Implementation {
fn dockerfile(&self) -> &'static str {
match self {
Implementation::Unbound => include_str!("docker/unbound.Dockerfile"),
Implementation::Hickory => include_str!("docker/hickory.Dockerfile"),
Implementation::Hickory { .. } => include_str!("docker/hickory.Dockerfile"),
}
}
@ -41,7 +41,8 @@ impl Implementation {
static UNBOUND_ONCE: Once = Once::new();
&UNBOUND_ONCE
}
Implementation::Hickory => {
Implementation::Hickory { .. } => {
static HICKORY_ONCE: Once = Once::new();
&HICKORY_ONCE
}
@ -59,7 +60,7 @@ impl fmt::Display for Implementation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Implementation::Unbound => "unbound",
Implementation::Hickory => "hickory",
Implementation::Hickory { .. } => "hickory",
};
f.write_str(s)
}
@ -67,10 +68,20 @@ impl fmt::Display for Implementation {
pub fn subject() -> Implementation {
if let Ok(subject) = std::env::var("DNS_TEST_SUBJECT") {
match subject.as_str() {
"hickory" => Implementation::Hickory,
"unbound" => Implementation::Unbound,
_ => panic!("unknown implementation: {subject}"),
if subject == "unbound" {
return Implementation::Unbound;
}
if subject.starts_with("hickory") {
if let Some(url) = subject.strip_prefix("hickory ") {
Implementation::Hickory {
url: url.to_string(),
}
} else {
panic!("the syntax of DNS_TEST_SUBJECT is 'hickory $URL', e.g. 'hickory /tmp/hickory' or 'hickory https://github.com/owner/repo'")
}
} else {
panic!("unknown implementation: {subject}")
}
} else {
Implementation::default()

View File

@ -43,7 +43,7 @@ impl<'a> NameServer<'a, Stopped> {
});
Ok(Self {
container: Container::run(Implementation::Unbound, network)?,
container: Container::run(&Implementation::Unbound, network)?,
zone_file,
state: Stopped,
})

View File

@ -33,7 +33,7 @@ impl Resolver {
"must configure at least one local root server"
);
let container = Container::run(implementation, network)?;
let container = Container::run(&implementation, network)?;
let mut hints = String::new();
for root in roots {
@ -51,7 +51,7 @@ impl Resolver {
)?;
}
Implementation::Hickory => {
Implementation::Hickory { .. } => {
container.status_ok(&["mkdir", "-p", "/etc/hickory"])?;
container.cp("/etc/hickory/root.hints", &hints)?;
@ -66,7 +66,7 @@ impl Resolver {
let command: &[_] = match implementation {
Implementation::Unbound => &["unbound", "-d"],
Implementation::Hickory => &["hickory-dns", "-d"],
Implementation::Hickory { .. } => &["hickory-dns", "-d"],
};
let child = container.spawn(command)?;