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