zombienet_provider/native/
provider.rs1use 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 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}