Disconnect all containers before removing network
The list of attached containers is determined, all of them are disconnected from the network, then the network is deleted. * set net mask in unbound conf template * expose container id
This commit is contained in:
parent
820f1c3447
commit
2289567998
|
@ -54,6 +54,7 @@ impl Container {
|
|||
command
|
||||
.args(["run", "--rm", "--detach", "--name", &name])
|
||||
.arg("-it")
|
||||
.args(["--network", network.name()])
|
||||
.arg(image_tag)
|
||||
.args(["sleep", "infinity"]);
|
||||
|
||||
|
@ -154,6 +155,10 @@ impl Container {
|
|||
pub fn ipv4_addr(&self) -> Ipv4Addr {
|
||||
self.inner.ipv4_addr
|
||||
}
|
||||
|
||||
pub fn id(&self) -> &str {
|
||||
&self.inner.id
|
||||
}
|
||||
}
|
||||
|
||||
fn container_count() -> usize {
|
||||
|
|
|
@ -24,7 +24,7 @@ impl Network {
|
|||
let mut command = Command::new("docker");
|
||||
command
|
||||
.args(["network", "create"])
|
||||
.args(["--internal"])
|
||||
.args(["--internal", "--attachable"])
|
||||
.arg(&network_name);
|
||||
|
||||
// create network
|
||||
|
@ -49,6 +49,11 @@ impl Network {
|
|||
pub fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
/// Returns the subnet mask
|
||||
pub fn netmask(&self) -> &str {
|
||||
&self.config.subnet
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects all important configs.
|
||||
|
@ -85,7 +90,20 @@ impl Drop for Network {
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes the given network.
|
||||
fn remove_network(network_name: &str) -> Result<ExitStatus> {
|
||||
// Disconnects all attached containers
|
||||
for container_id in get_attached_containers(network_name)? {
|
||||
let mut command = Command::new("docker");
|
||||
let _ = command
|
||||
.args(["network", "disconnect", "--force"])
|
||||
.args([network_name, container_id.as_str()])
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status()?;
|
||||
}
|
||||
|
||||
// Remove the network
|
||||
let mut command = Command::new("docker");
|
||||
command
|
||||
.args(["network", "rm", "--force", network_name])
|
||||
|
@ -94,6 +112,35 @@ fn remove_network(network_name: &str) -> Result<ExitStatus> {
|
|||
Ok(command.status()?)
|
||||
}
|
||||
|
||||
/// Finds the list of connected containers
|
||||
fn get_attached_containers(network_name: &str) -> Result<Vec<String>> {
|
||||
let mut command = Command::new("docker");
|
||||
command.args([
|
||||
"network",
|
||||
"inspect",
|
||||
network_name,
|
||||
"-f",
|
||||
r#"{{ range $k, $v := .Containers }}{{ printf "%s\n" $k }}{{ end }}"#,
|
||||
]);
|
||||
|
||||
let output = command.output()?;
|
||||
let container_ids = match output.status.success() {
|
||||
true => {
|
||||
let container_ids = std::str::from_utf8(&output.stdout)?
|
||||
.trim()
|
||||
.to_string()
|
||||
.lines()
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| line.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
container_ids
|
||||
}
|
||||
false => vec![],
|
||||
};
|
||||
|
||||
Ok(container_ids)
|
||||
}
|
||||
|
||||
fn network_count() -> usize {
|
||||
static COUNT: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
|
@ -102,6 +149,8 @@ fn network_count() -> usize {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{name_server::NameServer, FQDN};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -117,4 +166,22 @@ mod tests {
|
|||
assert!(config.is_ok());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_network_works() -> Result<()> {
|
||||
let network = Network::new().expect("Failed to create network");
|
||||
let network_name = network.name().to_string();
|
||||
let nameserver = NameServer::new(FQDN::ROOT, &network)?;
|
||||
|
||||
let container_ids = get_attached_containers(network.name())?;
|
||||
assert_eq!(1, container_ids.len());
|
||||
assert_eq!(&[nameserver.container_id().to_string()], &container_ids[..]);
|
||||
|
||||
drop(network);
|
||||
|
||||
let container_ids = get_attached_containers(&network_name)?;
|
||||
assert!(container_ids.is_empty());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,10 @@ impl<'a> NameServer<'a, Stopped> {
|
|||
state: Running { child },
|
||||
})
|
||||
}
|
||||
|
||||
pub fn container_id(&self) -> &str {
|
||||
self.container.id()
|
||||
}
|
||||
}
|
||||
|
||||
const ZONES_DIR: &str = "/etc/nsd/zones";
|
||||
|
|
|
@ -44,7 +44,10 @@ impl Resolver {
|
|||
Implementation::Unbound => {
|
||||
container.cp("/etc/unbound/root.hints", &hints)?;
|
||||
|
||||
container.cp("/etc/unbound/unbound.conf", &unbound_conf(use_dnssec))?;
|
||||
container.cp(
|
||||
"/etc/unbound/unbound.conf",
|
||||
&unbound_conf(use_dnssec, network.netmask()),
|
||||
)?;
|
||||
}
|
||||
|
||||
Implementation::Hickory => {
|
||||
|
@ -95,8 +98,8 @@ kill -TERM $(cat {pidfile})"
|
|||
}
|
||||
}
|
||||
|
||||
fn unbound_conf(use_dnssec: bool) -> String {
|
||||
minijinja::render!(include_str!("templates/unbound.conf.jinja"), use_dnssec => use_dnssec)
|
||||
fn unbound_conf(use_dnssec: bool, netmask: &str) -> String {
|
||||
minijinja::render!(include_str!("templates/unbound.conf.jinja"), use_dnssec => use_dnssec, netmask => netmask)
|
||||
}
|
||||
|
||||
fn hickory_conf(use_dnssec: bool) -> String {
|
||||
|
|
|
@ -2,7 +2,7 @@ server:
|
|||
verbosity: 4
|
||||
use-syslog: no
|
||||
interface: 0.0.0.0
|
||||
access-control: 172.17.0.0/16 allow
|
||||
access-control: {{ netmask }} allow
|
||||
root-hints: /etc/unbound/root.hints
|
||||
{% if use_dnssec %}
|
||||
trust-anchor-file: /etc/trusted-key.key
|
||||
|
|
Loading…
Reference in New Issue
Block a user