support docker runtime in dfinit with ut (#868)
Signed-off-by: cormick <cormick1080@gmail.com>
This commit is contained in:
parent
62c62f7ec6
commit
c93e01b005
|
|
@ -1016,6 +1016,7 @@ dependencies = [
|
||||||
"dragonfly-client",
|
"dragonfly-client",
|
||||||
"dragonfly-client-config",
|
"dragonfly-client-config",
|
||||||
"dragonfly-client-core",
|
"dragonfly-client-core",
|
||||||
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ bytesize-serde = "0.2.1"
|
||||||
percent-encoding = "2.3.1"
|
percent-encoding = "2.3.1"
|
||||||
tempfile = "3.14.0"
|
tempfile = "3.14.0"
|
||||||
tokio-rustls = "0.25.0-alpha.4"
|
tokio-rustls = "0.25.0-alpha.4"
|
||||||
|
serde_json = "1.0.132"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,4 @@ toml_edit.workspace = true
|
||||||
toml.workspace = true
|
toml.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use dragonfly_client_config::dfinit;
|
use dragonfly_client_config::dfinit;
|
||||||
use dragonfly_client_core::{Error, Result};
|
use dragonfly_client_core::{
|
||||||
|
error::{ErrorType, OrErr},
|
||||||
|
Error, Result,
|
||||||
|
};
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use tokio::{self, fs};
|
||||||
use tracing::{info, instrument};
|
use tracing::{info, instrument};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
/// Docker represents the docker runtime manager.
|
/// Docker represents the docker runtime manager.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -40,8 +46,6 @@ impl Docker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: Implement the run method for Docker.
|
|
||||||
///
|
|
||||||
/// run runs the docker runtime to initialize
|
/// run runs the docker runtime to initialize
|
||||||
/// runtime environment for the dfdaemon.
|
/// runtime environment for the dfdaemon.
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
|
|
@ -50,6 +54,200 @@ impl Docker {
|
||||||
"docker feature is enabled, proxy_addr: {}, config_path: {:?}",
|
"docker feature is enabled, proxy_addr: {}, config_path: {:?}",
|
||||||
self.proxy_config.addr, self.config.config_path,
|
self.proxy_config.addr, self.config.config_path,
|
||||||
);
|
);
|
||||||
Err(Error::Unimplemented)
|
|
||||||
|
// Parse proxy address to get host and port.
|
||||||
|
let proxy_url = Url::parse(&self.proxy_config.addr).or_err(ErrorType::ParseError)?;
|
||||||
|
let proxy_host = proxy_url
|
||||||
|
.host_str()
|
||||||
|
.ok_or(Error::Unknown("host not found".to_string()))?;
|
||||||
|
let proxy_port = proxy_url
|
||||||
|
.port_or_known_default()
|
||||||
|
.ok_or(Error::Unknown("port not found".to_string()))?;
|
||||||
|
let proxy_location = format!("{}:{}", proxy_host, proxy_port);
|
||||||
|
|
||||||
|
// Prepare proxies configuration.
|
||||||
|
let mut proxies_map = serde_json::Map::new();
|
||||||
|
proxies_map.insert(
|
||||||
|
"http-proxy".to_string(),
|
||||||
|
json!(format!("http://{}", proxy_location)),
|
||||||
|
);
|
||||||
|
proxies_map.insert(
|
||||||
|
"https-proxy".to_string(),
|
||||||
|
json!(format!("http://{}", proxy_location)),
|
||||||
|
);
|
||||||
|
|
||||||
|
let config_path = &self.config.config_path;
|
||||||
|
let mut docker_config: serde_json::Map<String, Value> = if config_path.exists() {
|
||||||
|
let contents = fs::read_to_string(config_path).await?;
|
||||||
|
if contents.trim().is_empty() {
|
||||||
|
serde_json::Map::new()
|
||||||
|
} else {
|
||||||
|
serde_json::from_str(&contents).or_err(ErrorType::ParseError)?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serde_json::Map::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Insert or update proxies configuration.
|
||||||
|
docker_config.insert("proxies".to_string(), Value::Object(proxies_map));
|
||||||
|
|
||||||
|
// Create config directory if it doesn't exist.
|
||||||
|
let config_dir = config_path
|
||||||
|
.parent()
|
||||||
|
.ok_or(Error::Unknown("invalid config path".to_string()))?;
|
||||||
|
fs::create_dir_all(config_dir).await?;
|
||||||
|
|
||||||
|
// Write configuration to file.
|
||||||
|
fs::write(
|
||||||
|
config_path,
|
||||||
|
serde_json::to_string_pretty(&Value::Object(docker_config))
|
||||||
|
.or_err(ErrorType::SerializeError)?,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
use tokio::fs;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_docker_config_empty() {
|
||||||
|
let docker_config_file = NamedTempFile::new().unwrap();
|
||||||
|
let docker = Docker::new(
|
||||||
|
dfinit::Docker {
|
||||||
|
config_path: docker_config_file.path().to_path_buf(),
|
||||||
|
},
|
||||||
|
dfinit::Proxy {
|
||||||
|
addr: "http://127.0.0.1:5000".into(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = docker.run().await;
|
||||||
|
println!("{:?}", result);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
// Read and verify configuration.
|
||||||
|
let contents = fs::read_to_string(docker_config_file.path()).await.unwrap();
|
||||||
|
let config: serde_json::Value = serde_json::from_str(&contents).unwrap();
|
||||||
|
|
||||||
|
// Verify proxies configuration.
|
||||||
|
assert_eq!(config["proxies"]["http-proxy"], "http://127.0.0.1:5000");
|
||||||
|
assert_eq!(config["proxies"]["https-proxy"], "http://127.0.0.1:5000");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_docker_config_existing() {
|
||||||
|
let docker_config_file = NamedTempFile::new().unwrap();
|
||||||
|
let initial_config = r#"
|
||||||
|
{
|
||||||
|
"log-driver": "json-file",
|
||||||
|
"experimental": true
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
fs::write(docker_config_file.path(), initial_config)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let docker = Docker::new(
|
||||||
|
dfinit::Docker {
|
||||||
|
config_path: docker_config_file.path().to_path_buf(),
|
||||||
|
},
|
||||||
|
dfinit::Proxy {
|
||||||
|
addr: "http://127.0.0.1:5000".into(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = docker.run().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
// Read and verify configuration.
|
||||||
|
let contents = fs::read_to_string(docker_config_file.path()).await.unwrap();
|
||||||
|
let config: serde_json::Value = serde_json::from_str(&contents).unwrap();
|
||||||
|
|
||||||
|
// Verify existing configurations.
|
||||||
|
assert_eq!(config["log-driver"], "json-file");
|
||||||
|
assert_eq!(config["experimental"], true);
|
||||||
|
|
||||||
|
// Verify proxies configuration.
|
||||||
|
assert_eq!(config["proxies"]["http-proxy"], "http://127.0.0.1:5000");
|
||||||
|
assert_eq!(config["proxies"]["https-proxy"], "http://127.0.0.1:5000");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_docker_config_invalid_json() {
|
||||||
|
let docker_config_file = NamedTempFile::new().unwrap();
|
||||||
|
let invalid_config = r#"
|
||||||
|
{
|
||||||
|
"log-driver": "json-file",
|
||||||
|
"experimental": true,
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
fs::write(docker_config_file.path(), invalid_config)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let docker = Docker::new(
|
||||||
|
dfinit::Docker {
|
||||||
|
config_path: docker_config_file.path().to_path_buf(),
|
||||||
|
},
|
||||||
|
dfinit::Proxy {
|
||||||
|
addr: "http://127.0.0.1:5000".into(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = docker.run().await;
|
||||||
|
assert!(result.is_err());
|
||||||
|
if let Err(e) = result {
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", e),
|
||||||
|
"ParseError cause: trailing comma at line 5 column 9"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_docker_config_proxies_existing() {
|
||||||
|
let docker_config_file = NamedTempFile::new().unwrap();
|
||||||
|
let existing_proxies = r#"
|
||||||
|
{
|
||||||
|
"proxies": {
|
||||||
|
"http-proxy": "http://old-proxy:3128",
|
||||||
|
"https-proxy": "https://old-proxy:3129",
|
||||||
|
"no-proxy": "old-no-proxy"
|
||||||
|
},
|
||||||
|
"log-driver": "json-file"
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
fs::write(docker_config_file.path(), existing_proxies)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let docker = Docker::new(
|
||||||
|
dfinit::Docker {
|
||||||
|
config_path: docker_config_file.path().to_path_buf(),
|
||||||
|
},
|
||||||
|
dfinit::Proxy {
|
||||||
|
addr: "http://127.0.0.1:5000".into(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = docker.run().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
|
||||||
|
// Read and verify configuration.
|
||||||
|
let contents = fs::read_to_string(docker_config_file.path()).await.unwrap();
|
||||||
|
let config: serde_json::Value = serde_json::from_str(&contents).unwrap();
|
||||||
|
|
||||||
|
// Verify existing configurations.
|
||||||
|
assert_eq!(config["log-driver"], "json-file");
|
||||||
|
|
||||||
|
// Verify proxies configuration.
|
||||||
|
assert_eq!(config["proxies"]["http-proxy"], "http://127.0.0.1:5000");
|
||||||
|
assert_eq!(config["proxies"]["https-proxy"], "http://127.0.0.1:5000");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ bytesize.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
percent-encoding.workspace = true
|
percent-encoding.workspace = true
|
||||||
tokio-rustls.workspace = true
|
tokio-rustls.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
lazy_static = "1.5"
|
lazy_static = "1.5"
|
||||||
serde_json = "1.0"
|
|
||||||
tracing-log = "0.2"
|
tracing-log = "0.2"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "time", "chrono"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "time", "chrono"] }
|
||||||
tracing-appender = "0.2.3"
|
tracing-appender = "0.2.3"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue