Skip to main content

container_device_interface/generate/
config.rs

1use std::collections::HashMap;
2
3use oci_spec::runtime::{Hooks, Linux, LinuxIntelRdt, LinuxResources, Mount, Process, Spec};
4
5pub struct Generator {
6    pub config: Option<Spec>,
7    pub host_specific: bool,
8    pub env_map: HashMap<String, usize>,
9}
10
11impl Generator {
12    pub fn spec_gen(spec: Option<Spec>) -> Self {
13        Generator {
14            config: spec,
15            host_specific: false,
16            env_map: HashMap::new(),
17        }
18    }
19
20    pub fn init_config(&mut self) {
21        if self.config.is_none() {
22            self.config = Some(Spec::default());
23        }
24    }
25
26    pub fn init_config_process(&mut self) {
27        self.init_config();
28
29        let spec = self.config.as_mut().unwrap();
30        if spec.process().is_none() {
31            spec.set_process(Some(Process::default()));
32        }
33    }
34
35    pub fn init_config_linux(&mut self) {
36        self.init_config();
37
38        let spec = self.config.as_mut().unwrap();
39        if spec.linux().is_none() {
40            spec.set_linux(Some(Linux::default()));
41        }
42    }
43
44    pub fn init_config_linux_resources(&mut self) {
45        self.init_config_linux();
46
47        let linux = self.config.as_mut().unwrap().linux_mut().as_mut().unwrap();
48        if linux.resources().is_none() {
49            linux.set_resources(Some(LinuxResources::default()));
50        }
51    }
52
53    pub fn init_config_linux_resources_devices(&mut self) {
54        self.init_config_linux_resources();
55
56        let linux = self.config.as_mut().unwrap().linux_mut().as_mut().unwrap();
57        let resource = linux.resources_mut().as_mut().unwrap();
58        if resource.devices().is_none() {
59            resource.set_devices(Some(Vec::new()));
60        }
61    }
62
63    pub fn init_config_linux_net_devices(&mut self) {
64        self.init_config_linux();
65
66        let linux = self.config.as_mut().unwrap().linux_mut().as_mut().unwrap();
67        if linux.net_devices().is_none() {
68            linux.set_net_devices(Some(HashMap::new()));
69        }
70    }
71
72    pub fn init_config_hooks(&mut self) {
73        self.init_config();
74
75        let spec = self.config.as_mut().unwrap();
76        if spec.hooks().is_none() {
77            spec.set_hooks(Some(Hooks::default()));
78        }
79    }
80
81    pub fn init_config_mounts(&mut self) {
82        self.init_config();
83
84        let spec = self.config.as_mut().unwrap();
85        if spec.mounts().is_none() {
86            spec.set_mounts(Some(vec![Mount::default()]));
87        }
88    }
89
90    pub fn init_config_linux_intel_rdt(&mut self) {
91        self.init_config_linux();
92
93        let linux = self.config.as_mut().unwrap().linux_mut().as_mut().unwrap();
94        if linux.intel_rdt().is_none() {
95            linux.set_intel_rdt(Some(LinuxIntelRdt::default()));
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    // Each init_* must create the layer once and leave it alone after -
105    // calling twice exercises both branches.
106    #[test]
107    fn init_helpers_are_idempotent() {
108        // An all-None spec drives the create arms (serde defaults would
109        // repopulate, hence explicit setters); the second loop pass and the
110        // pre-populated Spec::default() drive the leave-alone arms.
111        let mut bare = Spec::default();
112        bare.set_process(None)
113            .set_linux(None)
114            .set_hooks(None)
115            .set_mounts(None);
116        // Linux::default() pre-populates resources: hollow it out layer by
117        // layer so the set_resources / set_devices create arms fire too.
118        let mut hollow_linux = Linux::default();
119        hollow_linux
120            .set_resources(None)
121            .set_net_devices(None)
122            .set_intel_rdt(None);
123        let mut spec_hollow_linux = Spec::default();
124        spec_hollow_linux.set_linux(Some(hollow_linux));
125        let mut resources_no_devices = LinuxResources::default();
126        resources_no_devices.set_devices(None);
127        let mut linux_no_devices = Linux::default();
128        linux_no_devices.set_resources(Some(resources_no_devices));
129        let mut spec_no_devices = Spec::default();
130        spec_no_devices.set_linux(Some(linux_no_devices));
131
132        for spec in [
133            Some(bare),
134            Some(spec_hollow_linux),
135            Some(spec_no_devices),
136            None,
137            Some(Spec::default()),
138        ] {
139            let mut g = Generator::spec_gen(spec);
140            g.init_config();
141            assert!(g.config.is_some());
142
143            for _ in 0..2 {
144                g.init_config_process();
145                g.init_config_linux();
146                g.init_config_linux_resources();
147                g.init_config_linux_resources_devices();
148                g.init_config_linux_net_devices();
149                g.init_config_hooks();
150                g.init_config_mounts();
151                g.init_config_linux_intel_rdt();
152            }
153
154            let spec = g.config.as_ref().unwrap();
155            assert!(spec.process().is_some());
156            assert!(spec.hooks().is_some());
157            assert!(spec.mounts().is_some());
158            let linux = spec.linux().as_ref().unwrap();
159            assert!(linux.resources().as_ref().unwrap().devices().is_some());
160            assert!(linux.net_devices().is_some());
161            assert!(linux.intel_rdt().is_some());
162        }
163    }
164}