use isoloom_plan::more_addresses::MoreAddresses;
use isoloom_spec::shell::quote;
#[must_use]
pub fn linux(addresses: &[MoreAddresses]) -> String {
addresses
.iter()
.map(|a| {
let find = quote(&format!(" inet {}/", a.primary));
let added: String = a
.more
.iter()
.map(|more| format!("ip addr replace {more}/{} dev \"$dev\"\n", a.prefix))
.collect::<Vec<_>>()
.concat();
format!("dev=$(ip -o -4 addr show | grep -F {find} | awk '{{print $2; exit}}')\n{added}")
})
.collect::<Vec<_>>()
.concat()
}
#[must_use]
pub fn windows(addresses: &[MoreAddresses]) -> String {
addresses
.iter()
.flat_map(|a| {
a.more.iter().map(move |more| {
format!(
"if (-not (Get-NetIPAddress -IPAddress '{more}' -ErrorAction SilentlyContinue)) {{ New-NetIPAddress -InterfaceIndex (Get-NetIPAddress -IPAddress '{}').InterfaceIndex -IPAddress '{more}' -PrefixLength {} -SkipAsSource $true | Out-Null }}",
a.primary, a.prefix
)
})
})
.collect::<Vec<_>>()
.join("\n")
}
#[cfg(test)]
mod tests {
use super::*;
fn web() -> Vec<MoreAddresses> {
vec![MoreAddresses {
primary: "10.0.0.10".parse().unwrap(),
prefix: 24,
more: vec!["10.0.0.11".parse().unwrap(), "10.0.0.12".parse().unwrap()],
}]
}
#[test]
fn each_address_lands_on_the_interface_of_the_primary_one() {
let sh = linux(&web());
assert!(sh.starts_with("dev=$(ip -o -4 addr show | grep -F ' inet 10.0.0.10/'"), "{sh}");
assert!(
sh.contains("ip addr replace 10.0.0.11/24 dev \"$dev\"\nip addr replace 10.0.0.12/24 dev \"$dev\"\n"),
"{sh}"
);
let ps = windows(&web());
assert_eq!(ps.lines().count(), 2, "{ps}");
assert!(
ps.contains("(Get-NetIPAddress -IPAddress '10.0.0.10').InterfaceIndex -IPAddress '10.0.0.11' -PrefixLength 24 -SkipAsSource $true"),
"{ps}"
);
}
}