move validation to Domain ctor
This commit is contained in:
parent
bab595a412
commit
1b0f1ef59f
@ -1,4 +1,5 @@
|
|||||||
use std::{net::Ipv4Addr, process::Child};
|
use std::net::Ipv4Addr;
|
||||||
|
use std::process::Child;
|
||||||
|
|
||||||
use crate::{container::Container, Domain, Result, CHMOD_RW_EVERYONE};
|
use crate::{container::Container, Domain, Result, CHMOD_RW_EVERYONE};
|
||||||
|
|
||||||
@ -14,15 +15,12 @@ impl AuthoritativeNameServer {
|
|||||||
container.status_ok(&["mkdir", "-p", "/etc/nsd/zones"])?;
|
container.status_ok(&["mkdir", "-p", "/etc/nsd/zones"])?;
|
||||||
|
|
||||||
let zone_path = "/etc/nsd/zones/main.zone";
|
let zone_path = "/etc/nsd/zones/main.zone";
|
||||||
container.cp(
|
container.cp("/etc/nsd/nsd.conf", &nsd_conf(domain), CHMOD_RW_EVERYONE)?;
|
||||||
"/etc/nsd/nsd.conf",
|
|
||||||
&nsd_conf(domain.fqdn()),
|
|
||||||
CHMOD_RW_EVERYONE,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let zone_file_contents = match domain {
|
let zone_file_contents = if domain.is_root() {
|
||||||
Domain::Root => root_zone(),
|
root_zone()
|
||||||
Domain::Tld { domain } => tld_zone(domain),
|
} else {
|
||||||
|
tld_zone(domain)
|
||||||
};
|
};
|
||||||
|
|
||||||
container.cp(zone_path, &zone_file_contents, CHMOD_RW_EVERYONE)?;
|
container.cp(zone_path, &zone_file_contents, CHMOD_RW_EVERYONE)?;
|
||||||
@ -43,13 +41,12 @@ impl Drop for AuthoritativeNameServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tld_zone(domain: &str) -> String {
|
fn tld_zone(domain: Domain) -> String {
|
||||||
assert!(domain.ends_with('.'));
|
assert!(!domain.is_root());
|
||||||
assert!(!domain.starts_with('.'));
|
|
||||||
|
|
||||||
minijinja::render!(
|
minijinja::render!(
|
||||||
include_str!("templates/tld.zone.jinja"),
|
include_str!("templates/tld.zone.jinja"),
|
||||||
tld => domain,
|
tld => domain.as_str()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,12 +54,10 @@ fn root_zone() -> String {
|
|||||||
minijinja::render!(include_str!("templates/root.zone.jinja"),)
|
minijinja::render!(include_str!("templates/root.zone.jinja"),)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nsd_conf(domain: &str) -> String {
|
fn nsd_conf(domain: Domain) -> String {
|
||||||
assert!(domain.ends_with('.'));
|
|
||||||
|
|
||||||
minijinja::render!(
|
minijinja::render!(
|
||||||
include_str!("templates/nsd.conf.jinja"),
|
include_str!("templates/nsd.conf.jinja"),
|
||||||
domain => domain
|
domain => domain.as_str()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +67,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("com.")?)?;
|
||||||
let ip_addr = tld_ns.ipv4_addr();
|
let ip_addr = tld_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Container::run()?;
|
let client = Container::run()?;
|
||||||
@ -87,7 +82,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.ipv4_addr();
|
let ip_addr = root_ns.ipv4_addr();
|
||||||
|
|
||||||
let client = Container::run()?;
|
let client = Container::run()?;
|
||||||
|
32
src/domain.rs
Normal file
32
src/domain.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Domain<'a> {
|
||||||
|
inner: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO likely needs further validation
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Domain(input: &str) -> Result<Domain<'_>> {
|
||||||
|
if !input.ends_with('.') {
|
||||||
|
return Err("domain must end with a `.`".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if input != "." && input.starts_with('.') {
|
||||||
|
return Err("non-root domain cannot start with a `.`".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Domain { inner: input })
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Domain<'a> {
|
||||||
|
pub const ROOT: Domain<'static> = Domain { inner: "." };
|
||||||
|
|
||||||
|
pub fn is_root(&self) -> bool {
|
||||||
|
self.inner == "."
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
}
|
16
src/lib.rs
16
src/lib.rs
@ -1,4 +1,5 @@
|
|||||||
pub use crate::authoritative_name_server::AuthoritativeNameServer;
|
pub use crate::authoritative_name_server::AuthoritativeNameServer;
|
||||||
|
pub use crate::domain::Domain;
|
||||||
pub use crate::recursive_resolver::RecursiveResolver;
|
pub use crate::recursive_resolver::RecursiveResolver;
|
||||||
|
|
||||||
pub type Error = Box<dyn std::error::Error>;
|
pub type Error = Box<dyn std::error::Error>;
|
||||||
@ -8,18 +9,5 @@ const CHMOD_RW_EVERYONE: &str = "666";
|
|||||||
|
|
||||||
mod authoritative_name_server;
|
mod authoritative_name_server;
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
mod domain;
|
||||||
mod recursive_resolver;
|
mod recursive_resolver;
|
||||||
|
|
||||||
pub enum Domain<'a> {
|
|
||||||
Root,
|
|
||||||
Tld { domain: &'a str },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Domain<'_> {
|
|
||||||
fn fqdn(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Domain::Root => ".",
|
|
||||||
Domain::Tld { domain } => domain,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -52,14 +52,14 @@ impl Drop for RecursiveResolver {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::AuthoritativeNameServer;
|
use crate::{AuthoritativeNameServer, Domain};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore = "FIXME"]
|
#[ignore = "FIXME"]
|
||||||
fn can_resolve() -> Result<()> {
|
fn can_resolve() -> Result<()> {
|
||||||
let root_ns = AuthoritativeNameServer::start(crate::Domain::Root)?;
|
let root_ns = AuthoritativeNameServer::start(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.ipv4_addr(),
|
ip_addr: root_ns.ipv4_addr(),
|
||||||
|
Loading…
Reference in New Issue
Block a user