container_device_interface/
default_cache.rs1use anyhow::Result;
2use std::collections::HashMap;
3use std::error::Error;
4use std::sync::{Arc, Mutex};
5
6use oci_spec::runtime::Spec;
7use once_cell::sync::OnceCell;
8
9use crate::cache::{new_cache, with_auto_refresh, Cache, CdiOption};
10
11static DEFAULT_CACHE: OnceCell<Arc<Mutex<Cache>>> = OnceCell::new();
14
15fn get_or_create_default_cache() -> Arc<Mutex<Cache>> {
16 DEFAULT_CACHE
17 .get_or_init(|| new_cache(vec![with_auto_refresh(true)]))
18 .clone()
19}
20
21pub fn get_default_cache() -> Arc<Mutex<Cache>> {
22 get_or_create_default_cache()
23}
24
25pub fn configure(options: Vec<CdiOption>) -> Result<()> {
26 let cache = get_or_create_default_cache();
27 let mut cache = cache.lock().unwrap();
28 if options.is_empty() {
29 return Ok(());
30 }
31 cache.configure(options);
32 Ok(())
33}
34
35pub fn refresh() -> Result<(), Box<dyn Error>> {
36 let cache = get_default_cache();
37 let mut cache = cache.lock().unwrap();
38 cache.refresh()
39}
40
41pub fn inject_devices(
42 oci_spec: &mut Spec,
43 devices: Vec<String>,
44) -> Result<Vec<String>, Box<dyn Error + Send + Sync + 'static>> {
45 let cache = get_default_cache();
46 let mut cache = cache.lock().unwrap();
47 cache.inject_devices(Some(oci_spec), devices)
48}
49
50pub fn list_devices() -> Vec<String> {
51 let cache = get_default_cache();
52 let mut cache = cache.lock().unwrap();
53 cache.list_devices()
54}
55
56pub fn get_errors() -> HashMap<String, Vec<anyhow::Error>> {
57 let cache = get_default_cache();
58 let cache = cache.lock().unwrap();
59 cache.get_errors()
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::spec_dirs::with_spec_dirs;
66 use std::fs;
67
68 #[test]
71 fn default_cache_is_a_singleton_and_configurable() {
72 let first = get_default_cache();
73 let second = get_default_cache();
74 assert!(
75 Arc::ptr_eq(&first, &second),
76 "get_default_cache must return the same instance"
77 );
78
79 let dir = tempfile::tempdir().unwrap();
80 fs::write(
81 dir.path().join("vendor.yaml"),
82 r#"cdiVersion: "0.6.0"
83kind: "vendor.com/device"
84devices:
85 - name: "gpu0"
86 containerEdits:
87 env:
88 - "VENDOR=1"
89"#,
90 )
91 .unwrap();
92
93 configure(vec![with_spec_dirs(&[dir.path().to_str().unwrap()])]).unwrap();
94 assert_eq!(
95 first.lock().unwrap().spec_dirs,
96 vec![dir.path().to_str().unwrap().to_string()],
97 "configure must act on the singleton"
98 );
99
100 configure(vec![]).unwrap();
102
103 refresh().unwrap();
104 assert_eq!(list_devices(), vec!["vendor.com/device=gpu0".to_string()]);
105 assert!(get_errors().is_empty());
106
107 let mut oci_spec = Spec::default();
108 inject_devices(&mut oci_spec, vec!["vendor.com/device=gpu0".to_string()]).unwrap();
109 let env = oci_spec.process().as_ref().unwrap().env().as_ref().unwrap();
110 assert!(env.contains(&"VENDOR=1".to_string()));
111 }
112}