use isoloom_spec::Spec;
use crate::document::{ProvisionDoc, SpecDoc};
use crate::draft::Draft;
use crate::{Error, LabFile, Result, Topology, cables, lans, machines, project, routers, starters, vlans};
#[derive(Debug, Clone, PartialEq)]
pub struct Compiled {
yaml: String,
spec: Spec,
files: Vec<LabFile>,
}
impl Compiled {
#[must_use]
pub fn yaml(&self) -> &str {
&self.yaml
}
#[must_use]
pub fn spec(&self) -> &Spec {
&self.spec
}
#[must_use]
pub fn files(&self) -> &[LabFile] {
&self.files
}
#[must_use]
pub fn into_parts(self) -> (String, Spec, Vec<LabFile>) {
(self.yaml, self.spec, self.files)
}
}
pub fn compile(topo: &Topology) -> Result<Compiled> {
cables::check_count(topo)?;
vlans::check_switch_names(topo)?;
let mut draft = Draft::default();
machines::add(topo, &mut draft)?;
lans::address(topo, &mut draft)?;
cables::allocate(topo, &mut draft)?;
routers::add_reach_rules(&mut draft);
routers::cisco_gateways(topo, &mut draft);
vlans::nest(topo, &mut draft);
let doc = SpecDoc {
version: 1,
name: topo.name.clone(),
networks: draft.networks,
reach: draft.reach,
machines: draft.machines,
provision: draft.controller.iter().map(ProvisionDoc::from).collect(),
};
let yaml = serde_yaml_ng::to_string(&doc).map_err(Error::Yaml)?;
let spec = isoloom_spec::syntax::parse(&yaml).map_err(Error::Unreadable)?;
let mut files = project::config_files(topo);
starters::add_starters(&mut files, &spec, &draft.controller);
Ok(Compiled { yaml, spec, files })
}