linuxkit_utils/cli/
linuxkit_make.rs

1use crate::AnyError;
2
3use crate::manifest::*;
4use crate::EnvSubst;
5
6use std::path::Path;
7
8#[derive(Debug, Clone, ::structopt::StructOpt)]
9pub struct LinuxkitMake {
10    #[structopt(default_value = ".")]
11    pub project_dir: String,
12}
13
14impl LinuxkitMake {
15    pub fn run(&self) -> Result<(), AnyError> {
16        let project_root: &Path = self.project_dir.as_str().as_ref();
17
18        let manifest = Manifest {
19            kernel: util::read_file(project_root.join("kernel.yml"))?,
20            init: util::read_dir_as_vec(project_root.join("init.d"))?,
21            on_boot: util::read_dir_as_vec(project_root.join("on-boot.d"))?,
22            on_shutdown: util::read_dir_as_vec(project_root.join("on-shutdown.d"))?,
23            services: util::read_dir_as_vec(project_root.join("services.d"))?,
24            files: util::read_dir_as_vec(project_root.join("files.d"))?,
25            trust: util::read_file(project_root.join("trust.yml"))?,
26        };
27
28        let manifest = manifest.env_subst(&std::env::vars().collect())?;
29
30        let stdout = std::io::stdout();
31        let stdout = stdout.lock();
32        let () = ::serde_yaml::to_writer(stdout, &manifest)?;
33
34        Ok(())
35    }
36}
37
38mod util {
39    use crate::AnyError;
40    use ::serde::de::DeserializeOwned;
41    use std::fs::OpenOptions;
42    use std::path::Path;
43
44    pub fn read_file<T, P>(path: P) -> Result<T, AnyError>
45    where
46        P: AsRef<Path>,
47        T: DeserializeOwned,
48    {
49        let f = OpenOptions::new().read(true).open(path)?;
50        let v = ::serde_yaml::from_reader(f)?;
51        Ok(v)
52    }
53
54    pub fn read_dir_as_vec<T, P>(path: P) -> Result<Vec<T>, AnyError>
55    where
56        P: AsRef<Path>,
57        T: DeserializeOwned,
58    {
59        let dir_entries = std::fs::read_dir(path)?;
60
61        let mut items = vec![];
62
63        for dir_entry in dir_entries {
64            let dir_entry = dir_entry?;
65
66            let file_name = dir_entry.file_name().to_string_lossy().as_ref().to_owned();
67
68            if !dir_entry.file_type()?.is_file() {
69                continue;
70            }
71
72            if !file_name.ends_with(".yml") {
73                continue;
74            }
75
76            let value = read_file::<T, _>(dir_entry.path())?;
77
78            items.push((file_name, value));
79        }
80
81        let () = items.sort_by_key(|(n, _)| n.to_owned());
82
83        Ok(items.into_iter().map(|(_, v)| v).collect())
84    }
85}