use crate::dynconfig::{
Dynconfig, SchedulerClusterConfigBlockList, SchedulerClusterConfigDownloadBlockList,
SchedulerClusterConfigUploadBlockList,
};
use dragonfly_client_config::dfdaemon::Config;
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct DownloadBlockListCheckParams {
pub url: Option<String>,
pub application: Option<String>,
pub tag: Option<String>,
pub priority: Option<i32>,
}
#[derive(Debug, Clone)]
pub struct UploadBlockListCheckParams {
pub url: Option<String>,
pub application: Option<String>,
pub tag: Option<String>,
}
pub struct BlockList {
config: Arc<Config>,
dynconfig: Arc<Dynconfig>,
}
impl BlockList {
pub fn new(config: Arc<Config>, dynconfig: Arc<Dynconfig>) -> Self {
Self { config, dynconfig }
}
async fn with_block_list<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&SchedulerClusterConfigBlockList) -> Option<R>,
{
let data = self.dynconfig.data.read().await;
let config = if self.config.seed_peer.enable {
data.seed_client_config
.as_ref()
.and_then(|config| config.block_list.as_ref())
} else {
data.client_config
.as_ref()
.and_then(|config| config.block_list.as_ref())
};
config.and_then(f)
}
pub async fn is_task_download_blocked(&self, params: &DownloadBlockListCheckParams) -> bool {
self.with_block_list(|block_list| {
let block_list = block_list.task.as_ref()?.download.as_ref()?;
Some(Self::is_download_blocked(block_list, params))
})
.await
.unwrap_or(false)
}
pub async fn is_persistent_task_download_blocked(
&self,
params: &DownloadBlockListCheckParams,
) -> bool {
self.with_block_list(|block_list| {
let block_list = block_list.persistent_task.as_ref()?.download.as_ref()?;
Some(Self::is_download_blocked(block_list, params))
})
.await
.unwrap_or(false)
}
pub async fn is_persistent_task_upload_blocked(
&self,
params: &UploadBlockListCheckParams,
) -> bool {
self.with_block_list(|block_list| {
let block_list = block_list.persistent_task.as_ref()?.upload.as_ref()?;
Some(Self::is_upload_blocked(block_list, params))
})
.await
.unwrap_or(false)
}
pub async fn is_persistent_cache_task_download_blocked(
&self,
params: &DownloadBlockListCheckParams,
) -> bool {
self.with_block_list(|block_list| {
let block_list = block_list
.persistent_cache_task
.as_ref()?
.download
.as_ref()?;
Some(Self::is_download_blocked(block_list, params))
})
.await
.unwrap_or(false)
}
pub async fn is_persistent_cache_task_upload_blocked(
&self,
params: &UploadBlockListCheckParams,
) -> bool {
self.with_block_list(|block_list| {
let block_list = block_list.persistent_cache_task.as_ref()?.upload.as_ref()?;
Some(Self::is_upload_blocked(block_list, params))
})
.await
.unwrap_or(false)
}
fn is_download_blocked(
block_list: &SchedulerClusterConfigDownloadBlockList,
params: &DownloadBlockListCheckParams,
) -> bool {
if let Some(url) = ¶ms.url {
if block_list
.urls
.iter()
.any(|blocked_url| blocked_url.is_match(url))
{
return true;
}
}
if let (Some(application), Some(blocked_applications)) =
(¶ms.application, &block_list.applications)
{
if blocked_applications.contains(application) {
return true;
}
}
if let (Some(tag), Some(blocked_tags)) = (¶ms.tag, &block_list.tags) {
if blocked_tags.contains(tag) {
return true;
}
}
if let (Some(priority), Some(blocked_priorities)) =
(¶ms.priority, &block_list.priorities)
{
if blocked_priorities.contains(priority) {
return true;
}
}
false
}
fn is_upload_blocked(
block_list: &SchedulerClusterConfigUploadBlockList,
params: &UploadBlockListCheckParams,
) -> bool {
if let Some(url) = ¶ms.url {
if block_list
.urls
.iter()
.any(|blocked_url| blocked_url.is_match(url))
{
return true;
}
}
if let (Some(application), Some(blocked_applications)) =
(¶ms.application, &block_list.applications)
{
if blocked_applications.contains(application) {
return true;
}
}
if let (Some(tag), Some(blocked_tags)) = (¶ms.tag, &block_list.tags) {
if blocked_tags.contains(tag) {
return true;
}
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use regex::Regex;
#[test]
fn test_is_download_blocked_by_application() {
let block_list = SchedulerClusterConfigDownloadBlockList {
applications: Some(vec!["blocked-app".to_string()]),
urls: Vec::new(),
tags: None,
priorities: None,
};
let params = DownloadBlockListCheckParams {
application: Some("blocked-app".to_string()),
url: None,
tag: None,
priority: None,
};
assert!(BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: Some("allowed-app".to_string()),
url: None,
tag: None,
priority: None,
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: None,
priority: None,
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_download_blocked_by_url_regex() {
let block_list = SchedulerClusterConfigDownloadBlockList {
applications: None,
urls: vec![
Regex::new(r".*\.blocked\.com.*").unwrap(),
Regex::new(r"^https://forbidden\.").unwrap(),
],
tags: None,
priorities: None,
};
let params = DownloadBlockListCheckParams {
application: None,
url: Some("https://example.blocked.com/file".to_string()),
tag: None,
priority: None,
};
assert!(BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: Some("https://forbidden.example.com/file".to_string()),
tag: None,
priority: None,
};
assert!(BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: Some("https://allowed.com/file".to_string()),
tag: None,
priority: None,
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: None,
priority: None,
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_download_blocked_by_tag() {
let block_list = SchedulerClusterConfigDownloadBlockList {
applications: None,
urls: Vec::new(),
tags: Some(vec!["blocked-tag".to_string()]),
priorities: None,
};
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: Some("blocked-tag".to_string()),
priority: None,
};
assert!(BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: Some("allowed-tag".to_string()),
priority: None,
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_download_blocked_by_priority() {
let block_list = SchedulerClusterConfigDownloadBlockList {
applications: None,
urls: Vec::new(),
tags: None,
priorities: Some(vec![0]),
};
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: None,
priority: Some(0),
};
assert!(BlockList::is_download_blocked(&block_list, ¶ms));
let params = DownloadBlockListCheckParams {
application: None,
url: None,
tag: None,
priority: Some(5),
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_download_blocked_empty_block_list() {
let block_list = SchedulerClusterConfigDownloadBlockList {
applications: None,
urls: Vec::new(),
tags: None,
priorities: None,
};
let params = DownloadBlockListCheckParams {
application: Some("any-app".to_string()),
url: Some("https://any.url.com".to_string()),
tag: Some("any-tag".to_string()),
priority: Some(1),
};
assert!(!BlockList::is_download_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_upload_blocked_by_application() {
let block_list = SchedulerClusterConfigUploadBlockList {
applications: Some(vec!["blocked-app".to_string()]),
urls: Vec::new(),
tags: None,
};
let params = UploadBlockListCheckParams {
application: Some("blocked-app".to_string()),
url: None,
tag: None,
};
assert!(BlockList::is_upload_blocked(&block_list, ¶ms));
let params = UploadBlockListCheckParams {
application: Some("allowed-app".to_string()),
url: None,
tag: None,
};
assert!(!BlockList::is_upload_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_upload_blocked_by_url_regex() {
let block_list = SchedulerClusterConfigUploadBlockList {
applications: None,
urls: vec![Regex::new(r".*blocked.*").unwrap()],
tags: None,
};
let params = UploadBlockListCheckParams {
application: None,
url: Some("https://blocked.com/upload".to_string()),
tag: None,
};
assert!(BlockList::is_upload_blocked(&block_list, ¶ms));
let params = UploadBlockListCheckParams {
application: None,
url: Some("https://allowed.com/upload".to_string()),
tag: None,
};
assert!(!BlockList::is_upload_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_upload_blocked_by_tag() {
let block_list = SchedulerClusterConfigUploadBlockList {
applications: None,
urls: Vec::new(),
tags: Some(vec!["blocked-tag".to_string()]),
};
let params = UploadBlockListCheckParams {
application: None,
url: None,
tag: Some("blocked-tag".to_string()),
};
assert!(BlockList::is_upload_blocked(&block_list, ¶ms));
let params = UploadBlockListCheckParams {
application: None,
url: None,
tag: Some("allowed-tag".to_string()),
};
assert!(!BlockList::is_upload_blocked(&block_list, ¶ms));
}
#[test]
fn test_is_upload_blocked_empty_block_list() {
let block_list = SchedulerClusterConfigUploadBlockList {
applications: None,
urls: Vec::new(),
tags: None,
};
let params = UploadBlockListCheckParams {
application: Some("any-app".to_string()),
url: Some("https://any.url.com".to_string()),
tag: Some("any-tag".to_string()),
};
assert!(!BlockList::is_upload_blocked(&block_list, ¶ms));
}
}