Skip to main content

isoloom_spec/model/
configuration.rs

1//! What configures a machine, as lowering hands it to the plan: its steps in the configuration
2//! model's three phases, for its OS, with the texts of the templates they fill in. The plan
3//! resolves it once per machine into its recipe (`isoloom_plan::configure::Recipe`), which every
4//! CM renderer reads; nothing below the plan renders it.
5
6use std::collections::BTreeMap;
7
8use crate::syntax::{OsRef, ProjectPath, Step};
9
10/// A machine's configuration: an app's `steps` (all of them `install`), or a catalogue entry's
11/// phases, resolved from what the author wrote. Set by lowering, never written in a spec.
12#[derive(Debug, Clone, PartialEq, Eq)]
13#[non_exhaustive]
14pub struct Configuration {
15    /// The OS it is resolved for: its family installs and starts things.
16    pub os: OsRef,
17    /// Install: an app's steps; an entry's `install` (which its official image skips).
18    pub install: Vec<Step>,
19    /// Configure: an entry's `configure`, run in every form.
20    pub configure: Vec<Step>,
21    /// Start: an entry's per-start preparation (an app has none in 1.0).
22    pub start: Vec<Step>,
23    /// The text of each template its steps fill in, by the template's `from`: an entry's own
24    /// (its placeholders filled in, the lab's left for the plan), or a project file read by the
25    /// caller that generates (`isoloom_plan::Lab::with_templates`).
26    pub files: BTreeMap<ProjectPath, String>,
27}
28
29impl Configuration {
30    /// An app's configuration on `os`: its steps, all of them installing.
31    #[must_use]
32    pub fn app(os: OsRef, steps: Vec<Step>) -> Configuration {
33        Configuration {
34            os,
35            install: steps,
36            configure: Vec::new(),
37            start: Vec::new(),
38            files: BTreeMap::new(),
39        }
40    }
41
42    /// A catalogue entry's configuration on `os`: its three phases, resolved, and the texts of
43    /// its templates by the `from` its steps name.
44    #[must_use]
45    pub fn entry(os: OsRef, install: Vec<Step>, configure: Vec<Step>, start: Vec<Step>, files: BTreeMap<ProjectPath, String>) -> Configuration {
46        Configuration {
47            os,
48            install,
49            configure,
50            start,
51            files,
52        }
53    }
54
55    /// Its steps, phase after phase.
56    pub fn steps(&self) -> impl Iterator<Item = &Step> {
57        self.install.iter().chain(&self.configure).chain(&self.start)
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn an_apps_steps_all_install_and_read_back_in_order() {
67        let os: OsRef = "debian@12".parse().unwrap();
68        let steps: Vec<Step> = serde_yaml_ng::from_str("[{ run: a.sh }, reboot]").unwrap();
69        let c = Configuration::app(os, steps.clone());
70        assert_eq!(c.install, steps);
71        assert!(c.configure.is_empty() && c.start.is_empty() && c.files.is_empty());
72        assert_eq!(c.steps().map(Step::kind).collect::<Vec<_>>(), ["run", "reboot"]);
73    }
74}