use std::collections::HashMap;
use unicase::UniCase;
use wildland_corex::TemplateValidator;
use wildland_dfs::storage_backends::StorageBackendFactory;
#[cfg(feature = "lfs")]
use wildland_storage_backend::lfs::{
template::LfsTemplateValidator,
template::LOCAL_FILESYSTEM_KEY,
LfsBackendFactory,
};
#[cfg(feature = "s3")]
use wildland_storage_backend::s3::{S3BackendFactory, S3TemplateValidator, S3_KEY};
cfg_if::cfg_if! {
if #[cfg(feature = "s3sc")] {
use wildland_storage_backend::s3sc::{S3ScBackendFactory, S3ScTemplateValidator, S3SC_KEY};
} else if #[cfg(feature = "s3sc_new")] {
use wildland_storage_backend::s3sc_new::{S3ScBackendFactory, S3ScTemplateValidator, S3SC_KEY};
}
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn init_storage_backend_factories() -> HashMap<UniCase<String>, Box<dyn StorageBackendFactory>>
{
let mut dfs_storage_factories: HashMap<UniCase<String>, Box<dyn StorageBackendFactory>> =
HashMap::new();
#[cfg(feature = "lfs")]
dfs_storage_factories.insert(LOCAL_FILESYSTEM_KEY.into(), Box::new(LfsBackendFactory {}));
#[cfg(feature = "s3")]
dfs_storage_factories.insert(S3_KEY.into(), Box::new(S3BackendFactory::new()));
#[cfg(feature = "s3sc")]
dfs_storage_factories.insert(S3SC_KEY.into(), Box::new(S3ScBackendFactory::new()));
#[cfg(feature = "s3sc_new")]
dfs_storage_factories.insert(S3SC_KEY.into(), Box::new(S3ScBackendFactory::new()));
dfs_storage_factories
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn init_template_validators() -> HashMap<UniCase<String>, Box<dyn TemplateValidator>> {
let mut template_validators: HashMap<UniCase<String>, Box<dyn TemplateValidator>> =
HashMap::new();
#[cfg(feature = "lfs")]
template_validators.insert(
LOCAL_FILESYSTEM_KEY.into(),
Box::<LfsTemplateValidator>::default(),
);
#[cfg(feature = "s3")]
template_validators.insert(S3_KEY.into(), Box::<S3TemplateValidator>::default());
#[cfg(feature = "s3sc")]
template_validators.insert(S3SC_KEY.into(), Box::<S3ScTemplateValidator>::default());
#[cfg(feature = "s3sc_new")]
template_validators.insert(S3SC_KEY.into(), Box::<S3ScTemplateValidator>::default());
template_validators
}
#[cfg(test)]
pub(crate) mod test {
use std::collections::HashMap;
use std::sync::{Arc, Mutex, RwLock};
use mockall::mock;
use rstest::fixture;
use uuid::{Bytes, Uuid};
use wildland_catlib::gql_catlib::GqlCatlib;
use wildland_corex::catlib_service::CatLibService;
use wildland_corex::storage_manager::StorageManager;
use wildland_corex::{
ContainerManager,
ContainerState,
LocalSecureStorage,
LssResult,
Storage,
};
use wildland_databases::redis_client::RedisClient;
use wildland_dfs::{
AbortFlag,
DfsFrontend,
DfsFrontendError,
DirEntry,
EventReceiver,
FsStat,
IStream,
NodeStat,
OStream,
ProgressReporter,
SpaceUsage,
UnixTimestamp,
WlPermissions,
};
use crate::api::cargo_lib::DfsApi;
use crate::multidevice_state::user_state::UserMultideviceState;
mock! {
pub DfsApi {}
impl DfsFrontend for DfsApi {
fn get_path(&self, identifier: String) -> Result<String, DfsFrontendError>;
fn read_dir(&self, path: String) -> Result<Vec<DirEntry>, DfsFrontendError>;
fn metadata(&self, path: String) -> Result<NodeStat, DfsFrontendError>;
fn remove_file(&self, path: String) -> Result<(), DfsFrontendError>;
fn rename(&self, old_path: String, new_path: String) -> Result<(), DfsFrontendError>;
fn set_permissions(
&self,
path: String,
permissions: WlPermissions,
) -> Result<(), DfsFrontendError>;
fn set_owner(&self, path: String) -> Result<(), DfsFrontendError>;
fn create_dir(&self, path: String) -> Result<(), DfsFrontendError>;
fn remove_dir(&self, path: String, is_recursive: bool) -> Result<(), DfsFrontendError>;
fn stat_fs(&self, path: String) -> Result<FsStat, DfsFrontendError>;
fn get_receiver(&self) -> Arc<Mutex<dyn EventReceiver>>;
fn mount(&self, storage: &Storage) -> Result<(), DfsFrontendError>;
fn get_space_usage(&self, storage: &Storage) -> Result<SpaceUsage, DfsFrontendError>;
fn is_accessible(&self, storage: &Storage) -> Result<bool, DfsFrontendError>;
fn download(
&self,
path: String,
output: Box<dyn OStream>,
progress_reporter: Box<dyn ProgressReporter>,
abort_flag: &AbortFlag,
) -> Result<(), DfsFrontendError>;
fn upload(
&self,
path: String,
input: Box<dyn IStream>,
progress_reporter: Box<dyn ProgressReporter>,
abort_flag: &AbortFlag,
creation_time: Option<UnixTimestamp>,
) -> Result<(), DfsFrontendError>;
}
}
#[fixture]
pub(crate) fn dfs_api_mock() -> DfsApi {
Arc::new(MockDfsApi::new())
}
#[fixture]
pub(crate) fn container_manager() -> ContainerManager {
let mut dfs_mock = MockDfsApi::new();
dfs_mock.expect_mount().returning(|_| Ok(()));
let storage_manager = StorageManager::new(Arc::new(dfs_mock));
ContainerManager::new(ContainerState::default(), storage_manager)
}
#[fixture]
pub(crate) fn catlib_service() -> CatLibService {
let catlib_gql_url = std::env::var("CATALOG_BACKEND_GQL_URL")
.unwrap_or_else(|_| "http://localhost:8000/graphql/".into());
let catlib = Arc::new(GqlCatlib::new(catlib_gql_url));
CatLibService::new(catlib).unwrap()
}
#[fixture]
#[once]
pub(crate) fn multidevice_client() -> RedisClient {
let uuid = uuid::Builder::from_random_bytes(rand::random::<Bytes>()).into_uuid();
let redis_url =
std::env::var("CARGO_REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379/0".into());
RedisClient::new(redis_url, Some(uuid.to_string())).unwrap()
}
#[fixture]
pub(crate) fn multidevice_state(
#[default(Uuid::new_v4().to_string())] user_prefix: String,
multidevice_client: &RedisClient,
) -> UserMultideviceState {
let device_uuid = Uuid::new_v4();
UserMultideviceState::new(&user_prefix, &device_uuid.to_string(), multidevice_client)
}
#[fixture]
pub(crate) fn lss_stub() -> Box<dyn LocalSecureStorage> {
#[derive(Default)]
struct LssStub {
storage: RwLock<HashMap<String, String>>,
}
impl LocalSecureStorage for LssStub {
fn insert(&self, key: String, value: String) -> LssResult<Option<String>> {
Ok(self.storage.write().unwrap().insert(key, value))
}
fn get(&self, key: String) -> LssResult<Option<String>> {
Ok(self.storage.read().unwrap().get(&key).cloned())
}
fn contains_key(&self, key: String) -> LssResult<bool> {
Ok(self.storage.read().unwrap().contains_key(&key))
}
fn keys(&self) -> LssResult<Vec<String>> {
Ok(self.storage.read().unwrap().keys().cloned().collect())
}
fn keys_starting_with(&self, prefix: String) -> LssResult<Vec<String>> {
Ok(self
.storage
.read()
.unwrap()
.keys()
.filter(|key| key.starts_with(&prefix))
.cloned()
.collect())
}
fn remove(&self, key: String) -> LssResult<Option<String>> {
Ok(self.storage.write().unwrap().remove(&key))
}
fn len(&self) -> LssResult<usize> {
Ok(self.storage.read().unwrap().len())
}
fn is_empty(&self) -> LssResult<bool> {
Ok(self.storage.read().unwrap().is_empty())
}
}
Box::<LssStub>::default()
}
}