|
|
|
@ -27,12 +27,8 @@ fn main() { |
|
|
|
|
let nodes = hosts.iter().map(Host::to_dot_node); |
|
|
|
|
let edges = hosts.iter().flat_map(Host::to_dot_edge); |
|
|
|
|
|
|
|
|
|
// let edges = ..
|
|
|
|
|
|
|
|
|
|
//render it
|
|
|
|
|
|
|
|
|
|
println!("digraph antennen {{"); |
|
|
|
|
|
|
|
|
|
println!("graph antennen {{"); |
|
|
|
|
for node in nodes { |
|
|
|
|
println!("{}", node); |
|
|
|
|
} |
|
|
|
@ -55,15 +51,15 @@ pub enum ParseError { |
|
|
|
|
|
|
|
|
|
#[error_chain(custom)] |
|
|
|
|
#[error_chain(description = r#"|_| "Host file structure broken""#)] |
|
|
|
|
#[error_chain(display = r#"|t| write!(f, "the antenna config is wrong: {}", t)"#)] |
|
|
|
|
Structure(String), |
|
|
|
|
#[error_chain(display = r#"|&(ref name, ref err)| write!(f, "the antenna config of {} is wrong: {}", name, err)"#)] |
|
|
|
|
Structure((String, String)), |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
struct Host { |
|
|
|
|
name: String, |
|
|
|
|
ip: String, |
|
|
|
|
mac: String, |
|
|
|
|
mac: Option<String>, |
|
|
|
|
kind: HostKind, |
|
|
|
|
} |
|
|
|
|
impl Host { |
|
|
|
@ -71,20 +67,24 @@ impl Host { |
|
|
|
|
RawHost::from_file(path)?.parse() |
|
|
|
|
} |
|
|
|
|
fn to_dot_node(&self) -> String { |
|
|
|
|
let mac = self.mac.clone().unwrap_or("no mac".into()); |
|
|
|
|
let mut attributes = vec! |
|
|
|
|
[ "shape=record".to_string() |
|
|
|
|
, format!("label=\"{{\'{name}\'|{typ}|{{{ip}|{mac}}}|{{{ipv6}}}}}\"" |
|
|
|
|
, name = self.name, typ=self.kind.name(), ip=self.ip, mac=self.mac, ipv6="no ipv6") |
|
|
|
|
, name = self.name, typ=self.kind.name(), ip=self.ip |
|
|
|
|
, mac=mac, ipv6="no ipv6") |
|
|
|
|
, "style=filled".into() |
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
// type-specific handling
|
|
|
|
|
match self.kind { |
|
|
|
|
HostKind::Client {coordinates, ref subnet, .. } => attributes.extend_from_slice( |
|
|
|
|
&[ format!("pos=\"{breitengrad},{längengrad}\"" |
|
|
|
|
, längengrad=coordinates[0], breitengrad=coordinates[1]) |
|
|
|
|
, "fillcolor=lightgray".into() |
|
|
|
|
]), |
|
|
|
|
HostKind::Client {coordinates, ref subnet, .. } => |
|
|
|
|
{ attributes.push("fillcolor=lightgray".into()) |
|
|
|
|
; if let Some(coordinates) = coordinates |
|
|
|
|
{ attributes.push(format!("pos=\"{breitengrad},{längengrad}\"" |
|
|
|
|
, längengrad=coordinates[0], breitengrad=coordinates[1])) |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
_ => (), |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -95,7 +95,7 @@ impl Host { |
|
|
|
|
fn to_dot_edge(&self) -> Option<String> { |
|
|
|
|
match self.kind { |
|
|
|
|
HostKind::Client { ref parent, .. } => |
|
|
|
|
format!("\"{name}\" -> \"{parent}\"", name=self.name, parent=parent).into(), |
|
|
|
|
format!("\"{name}\" -- \"{parent}\"", name=self.name, parent=parent).into(), |
|
|
|
|
_ => None, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -103,7 +103,7 @@ impl Host { |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
enum HostKind { |
|
|
|
|
Client { subnet: String, coordinates: [f64;2], parent: String }, |
|
|
|
|
Client { subnet: String, coordinates: Option<[f64;2]>, parent: String }, |
|
|
|
|
AccessPoint, |
|
|
|
|
Other, |
|
|
|
|
} |
|
|
|
@ -127,7 +127,7 @@ struct RawHost { |
|
|
|
|
ansible_host: String, |
|
|
|
|
#[serde(rename = "type")] |
|
|
|
|
kind: String, |
|
|
|
|
mac: String, |
|
|
|
|
mac: Option<String>, |
|
|
|
|
client_of: Option<String>, |
|
|
|
|
coordinate: Option<[f64;2]>, |
|
|
|
|
subnet: Option<String>, |
|
|
|
@ -135,21 +135,22 @@ struct RawHost { |
|
|
|
|
|
|
|
|
|
impl RawHost { |
|
|
|
|
fn parse(self) -> Result<Host> { |
|
|
|
|
let name = self.name |
|
|
|
|
.ok_or(ParseError::Structure("got no file name? weird.".into()))? |
|
|
|
|
let name : String = self.name |
|
|
|
|
.ok_or(ParseError::Structure(("???".into(),"got no file name? weird.".into())))? |
|
|
|
|
.into_string().unwrap() |
|
|
|
|
.split('.') |
|
|
|
|
.next().unwrap().into(); |
|
|
|
|
Ok(Host |
|
|
|
|
{ name: name |
|
|
|
|
{ name: name.clone() |
|
|
|
|
, ip: self.ansible_host |
|
|
|
|
, mac: self.mac |
|
|
|
|
, kind: match self.kind.as_ref() |
|
|
|
|
{ "wlan-ap" => HostKind::AccessPoint |
|
|
|
|
, "client" => HostKind::Client |
|
|
|
|
{ subnet: self.subnet.ok_or(ParseError::Structure("is client, has no subnet".into()))? |
|
|
|
|
, coordinates: self.coordinate.ok_or(ParseError::Structure("is client, has no coordinates".into()))? |
|
|
|
|
, parent: self.client_of.ok_or(ParseError::Structure("is client, has no client_of".into()))? |
|
|
|
|
{ subnet: self.subnet.ok_or(ParseError::Structure((name.clone(), "is client, has no subnet".into())))? |
|
|
|
|
//, coordinates: self.coordinate.ok_or(ParseError::Structure("is client, has no coordinates".into()))?
|
|
|
|
|
, coordinates: self.coordinate |
|
|
|
|
, parent: self.client_of.ok_or(ParseError::Structure((name.clone(), "is client, has no client_of".into())))? |
|
|
|
|
} |
|
|
|
|
, _ => HostKind::Other |
|
|
|
|
} |
|
|
|
|