zombienet_provider/native/
provider.rs

1use std::{
2    collections::HashMap,
3    path::{Path, PathBuf},
4    sync::{Arc, Weak},
5};
6
7use async_trait::async_trait;
8use support::fs::FileSystem;
9use tokio::sync::RwLock;
10
11use super::namespace::NativeNamespace;
12use crate::{
13    types::ProviderCapabilities, DynNamespace, Provider, ProviderError, ProviderNamespace,
14};
15
16const PROVIDER_NAME: &str = "native";
17
18pub struct NativeProvider<FS>
19where
20    FS: FileSystem + Send + Sync + Clone,
21{
22    weak: Weak<NativeProvider<FS>>,
23    capabilities: ProviderCapabilities,
24    tmp_dir: PathBuf,
25    filesystem: FS,
26    pub(super) namespaces: RwLock<HashMap<String, Arc<NativeNamespace<FS>>>>,
27}
28
29impl<FS> NativeProvider<FS>
30where
31    FS: FileSystem + Send + Sync + Clone,
32{
33    pub fn new(filesystem: FS) -> Arc<Self> {
34        Arc::new_cyclic(|weak| NativeProvider {
35            weak: weak.clone(),
36            capabilities: ProviderCapabilities {
37                has_resources: false,
38                requires_image: false,
39                prefix_with_full_path: true,
40                use_default_ports_in_cmd: false,
41            },
42            // NOTE: temp_dir in linux return `/tmp` but on mac something like
43            //  `/var/folders/rz/1cyx7hfj31qgb98d8_cg7jwh0000gn/T/`, having
44            // one `trailing slash` and the other no can cause issues if
45            // you try to build a fullpath by concatenate. Use Pathbuf to prevent the issue.
46            tmp_dir: std::env::temp_dir(),
47            filesystem,
48            namespaces: RwLock::new(HashMap::new()),
49        })
50    }
51
52    pub fn tmp_dir(mut self, tmp_dir: impl Into<PathBuf>) -> Self {
53        self.tmp_dir = tmp_dir.into();
54        self
55    }
56}
57
58#[async_trait]
59impl<FS> Provider for NativeProvider<FS>
60where
61    FS: FileSystem + Send + Sync + Clone + 'static,
62{
63    fn name(&self) -> &str {
64        PROVIDER_NAME
65    }
66
67    fn capabilities(&self) -> &ProviderCapabilities {
68        &self.capabilities
69    }
70
71    async fn namespaces(&self) -> HashMap<String, DynNamespace> {
72        self.namespaces
73            .read()
74            .await
75            .iter()
76            .map(|(name, namespace)| (name.clone(), namespace.clone() as DynNamespace))
77            .collect()
78    }
79
80    async fn create_namespace(&self) -> Result<DynNamespace, ProviderError> {
81        let namespace = NativeNamespace::new(
82            &self.weak,
83            &self.tmp_dir,
84            &self.capabilities,
85            &self.filesystem,
86            None,
87        )
88        .await?;
89
90        self.namespaces
91            .write()
92            .await
93            .insert(namespace.name().to_string(), namespace.clone());
94
95        Ok(namespace)
96    }
97
98    async fn create_namespace_with_base_dir(
99        &self,
100        base_dir: &Path,
101    ) -> Result<DynNamespace, ProviderError> {
102        let namespace = NativeNamespace::new(
103            &self.weak,
104            &self.tmp_dir,
105            &self.capabilities,
106            &self.filesystem,
107            Some(base_dir),
108        )
109        .await?;
110
111        self.namespaces
112            .write()
113            .await
114            .insert(namespace.name().to_string(), namespace.clone());
115
116        Ok(namespace)
117    }
118}