添加qiming-rcoder模块
This commit is contained in:
303
qiming-rcoder/crates/docker_manager/src/lib.rs
Normal file
303
qiming-rcoder/crates/docker_manager/src/lib.rs
Normal file
@@ -0,0 +1,303 @@
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod container_self_inspector;
|
||||
pub mod container_state_actor;
|
||||
pub mod container_stop;
|
||||
pub mod image_selector;
|
||||
pub mod manager;
|
||||
pub mod path;
|
||||
pub mod types;
|
||||
pub mod utils;
|
||||
|
||||
// 新增模块
|
||||
pub mod container_builder;
|
||||
pub mod health;
|
||||
pub mod network;
|
||||
pub mod runtime_selection;
|
||||
|
||||
// Runtime abstraction (Docker/K8s selection)
|
||||
pub mod runtime;
|
||||
|
||||
pub use container_self_inspector::*;
|
||||
pub use container_state_actor::*;
|
||||
pub use manager::*;
|
||||
pub use types::*;
|
||||
pub use utils::*;
|
||||
|
||||
// 公共导出新模块
|
||||
pub use container_builder::{ContainerConfigBuilder, MountProcessor};
|
||||
pub use health::{
|
||||
HttpHealthChecker, ServiceHealthChecker, ServiceHealthStatus, wait_for_service_ready,
|
||||
};
|
||||
pub use network::{NetworkDetector, build_network_name, parse_project_from_network};
|
||||
pub use path::{
|
||||
HostPathResolver, get_host_path_resolver, normalize_path, resolve_container_path_to_host,
|
||||
};
|
||||
|
||||
/// Docker manager error type
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DockerError {
|
||||
#[error("docker connection failed: {0}")]
|
||||
ConnectionError(String),
|
||||
|
||||
#[error("container creation failed: {0}")]
|
||||
ContainerCreationError(String),
|
||||
|
||||
#[error("container start failed: {0}")]
|
||||
ContainerStartError(String),
|
||||
|
||||
#[error("container stop failed: {0}")]
|
||||
ContainerStopError(String),
|
||||
|
||||
#[error("container removal failed: {0}")]
|
||||
ContainerRemoveError(String),
|
||||
|
||||
#[error("image pull failed: {0}")]
|
||||
ImagePullError(String),
|
||||
|
||||
#[error("configuration error: {0}")]
|
||||
ConfigurationError(String),
|
||||
|
||||
#[error("IO error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("serialization error: {0}")]
|
||||
SerializationError(#[from] serde_json::Error),
|
||||
|
||||
#[error("timestamp parsing failed: {0}")]
|
||||
InvalidTimestamp(String),
|
||||
|
||||
#[error("docker API call timeout: {0}")]
|
||||
Timeout(String),
|
||||
|
||||
#[error("bollard docker error: {0}")]
|
||||
BollardError(#[from] bollard::errors::Error),
|
||||
}
|
||||
|
||||
/// Docker 管理器结果类型
|
||||
pub type DockerResult<T> = Result<T, DockerError>;
|
||||
|
||||
/// 默认的 Docker 镜像配置常量
|
||||
pub mod default_images {
|
||||
/// ARM64 架构的默认镜像
|
||||
pub const ARM64: &str = "registry.yichamao.com/agent-runner:latest-arm64";
|
||||
|
||||
/// AMD64 架构的默认镜像
|
||||
pub const AMD64: &str = "registry.yichamao.com/agent-runner:latest-amd64";
|
||||
|
||||
/// 默认回退镜像(当无法检测架构或架构不匹配时使用)
|
||||
pub const DEFAULT: &str = "registry.yichamao.com/agent-runner:latest";
|
||||
}
|
||||
|
||||
/// 默认的 Docker 镜像(根据架构自动选择)
|
||||
///
|
||||
/// 注意:此函数使用硬编码的默认值,建议使用 `get_docker_image_from_config()`
|
||||
/// 从配置中读取镜像地址
|
||||
pub fn default_docker_image() -> String {
|
||||
let platform = crate::utils::DockerUtils::auto_detect_platform();
|
||||
match platform.as_str() {
|
||||
"linux/arm64" => default_images::ARM64.to_string(),
|
||||
"linux/amd64" => default_images::AMD64.to_string(),
|
||||
_ => default_images::DEFAULT.to_string(), // 默认回退
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取默认的 ARM64 镜像
|
||||
pub fn default_arm64_image() -> String {
|
||||
default_images::ARM64.to_string()
|
||||
}
|
||||
|
||||
/// 获取默认的 AMD64 镜像
|
||||
pub fn default_amd64_image() -> String {
|
||||
default_images::AMD64.to_string()
|
||||
}
|
||||
|
||||
/// 获取默认的回退镜像
|
||||
pub fn default_fallback_image() -> String {
|
||||
default_images::DEFAULT.to_string()
|
||||
}
|
||||
|
||||
/// 从 rcoder 配置获取 Docker 镜像
|
||||
///
|
||||
/// # 参数
|
||||
/// * `image` - 通用镜像(优先使用,如果指定则忽略架构特定镜像)
|
||||
/// * `arm64_image` - ARM64 架构专用镜像
|
||||
/// * `amd64_image` - AMD64 架构专用镜像
|
||||
/// * `default_image` - 默认回退镜像(当无法检测架构或架构不匹配时使用)
|
||||
pub fn get_docker_image_from_config(
|
||||
image: Option<String>,
|
||||
arm64_image: Option<String>,
|
||||
amd64_image: Option<String>,
|
||||
default_image: Option<String>,
|
||||
) -> String {
|
||||
let platform = crate::utils::DockerUtils::auto_detect_platform();
|
||||
|
||||
// 优先使用通用镜像
|
||||
if let Some(img) = image {
|
||||
return img;
|
||||
}
|
||||
|
||||
// 根据架构使用特定镜像
|
||||
match platform.as_str() {
|
||||
"linux/arm64" => arm64_image.unwrap_or_else(|| {
|
||||
default_image.unwrap_or_else(|| default_images::DEFAULT.to_string())
|
||||
}),
|
||||
"linux/amd64" => amd64_image.unwrap_or_else(|| {
|
||||
default_image.unwrap_or_else(|| default_images::DEFAULT.to_string())
|
||||
}),
|
||||
_ => default_image.unwrap_or_else(|| default_images::DEFAULT.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// 默认的平台(使用自动检测)
|
||||
pub fn default_platform() -> String {
|
||||
crate::utils::DockerUtils::auto_detect_platform()
|
||||
}
|
||||
|
||||
/// 默认的工作目录
|
||||
pub const DEFAULT_WORK_DIR: &str = "/app";
|
||||
|
||||
/// 默认的网络模式
|
||||
pub const DEFAULT_NETWORK_MODE: &str = "bridge";
|
||||
|
||||
/// RCoder 专用网络名称(基础名称,不含 project name 前缀)
|
||||
/// Docker Compose 会自动添加 project name 前缀,实际网络名称为 {project_name}_{network_name}
|
||||
/// 例如: rcoder_agent-network, myapp_agent-network
|
||||
///
|
||||
/// ⚠️ 注意:实际使用时必须动态检测主容器所在的网络,不能硬编码
|
||||
pub const RCODER_NETWORK_BASE_NAME: &str = "agent-network";
|
||||
|
||||
/// 全局 Docker 管理器实例
|
||||
pub mod global {
|
||||
use super::*;
|
||||
#[cfg(feature = "kubernetes")]
|
||||
use crate::runtime_selection::RuntimeType;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::OnceCell;
|
||||
use tracing::{debug, info};
|
||||
|
||||
/// 全局 DockerManager 单例(用于向后兼容)
|
||||
static GLOBAL_DOCKER_MANAGER: OnceCell<Arc<DockerManager>> = OnceCell::const_new();
|
||||
|
||||
/// 初始化全局 DockerManager
|
||||
pub async fn init_global_docker_manager() -> DockerResult<()> {
|
||||
let config = DockerManagerConfig::default();
|
||||
let manager = Arc::new(DockerManager::new(config).await?);
|
||||
|
||||
GLOBAL_DOCKER_MANAGER.set(manager).map_err(|_| {
|
||||
DockerError::IoError(std::io::Error::new(
|
||||
std::io::ErrorKind::AlreadyExists,
|
||||
"global DockerManager already initialized",
|
||||
))
|
||||
})?;
|
||||
|
||||
info!("DockerManager initialized");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 使用自定义配置初始化全局 DockerManager
|
||||
///
|
||||
/// 注意:此函数保持向后兼容。对于 K8s 支持,请使用 init_global_runtime()
|
||||
#[cfg(feature = "kubernetes")]
|
||||
pub async fn init_global_docker_manager_with_config(
|
||||
config: DockerManagerConfig,
|
||||
) -> DockerResult<()> {
|
||||
let runtime_type = RuntimeType::from_env();
|
||||
crate::runtime::RuntimeManager::init(config.clone())
|
||||
.await
|
||||
.map_err(|e| DockerError::ConfigurationError(e.to_string()))?;
|
||||
info!("Runtime initialized with config");
|
||||
|
||||
if runtime_type == RuntimeType::Docker {
|
||||
let manager = Arc::new(DockerManager::new(config).await?);
|
||||
GLOBAL_DOCKER_MANAGER.set(manager).map_err(|_| {
|
||||
DockerError::IoError(std::io::Error::new(
|
||||
std::io::ErrorKind::AlreadyExists,
|
||||
"global DockerManager already initialized",
|
||||
))
|
||||
})?;
|
||||
info!("DockerManager initialized with config");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 使用自定义配置初始化全局 DockerManager(无 K8s 支持)
|
||||
#[cfg(not(feature = "kubernetes"))]
|
||||
pub async fn init_global_docker_manager_with_config(
|
||||
config: DockerManagerConfig,
|
||||
) -> DockerResult<()> {
|
||||
// Initialize RuntimeManager so RUNTIME_INSTANCE is set
|
||||
// This allows RuntimeManager::get() to work in docker compose mode
|
||||
crate::runtime::RuntimeManager::init(config.clone())
|
||||
.await
|
||||
.map_err(|e| DockerError::ConfigurationError(e.to_string()))?;
|
||||
info!("Runtime initialized with config");
|
||||
|
||||
let manager = Arc::new(DockerManager::new(config).await?);
|
||||
GLOBAL_DOCKER_MANAGER.set(manager).map_err(|_| {
|
||||
DockerError::IoError(std::io::Error::new(
|
||||
std::io::ErrorKind::AlreadyExists,
|
||||
"global DockerManager already initialized",
|
||||
))
|
||||
})?;
|
||||
info!("DockerManager initialized with config");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 初始化全局运行时(RuntimeManager)
|
||||
///
|
||||
/// 根据 CONTAINER_RUNTIME 环境变量选择 Docker 或 Kubernetes 运行时
|
||||
#[cfg(feature = "kubernetes")]
|
||||
pub async fn init_global_runtime(
|
||||
config: DockerManagerConfig,
|
||||
) -> container_runtime_api::ContainerRuntimeResult<()> {
|
||||
crate::runtime::RuntimeManager::init(config).await
|
||||
}
|
||||
|
||||
/// 获取全局运行时实例(Arc<dyn ContainerRuntime>)
|
||||
///
|
||||
/// 支持 Docker 和 Kubernetes 运行时
|
||||
#[cfg(feature = "kubernetes")]
|
||||
pub async fn get_global_runtime(
|
||||
) -> container_runtime_api::ContainerRuntimeResult<Arc<dyn container_runtime_api::ContainerRuntime>> {
|
||||
crate::runtime::RuntimeManager::get().await
|
||||
}
|
||||
|
||||
/// 获取全局 DockerManager 实例
|
||||
///
|
||||
/// 注意:此函数仅在 Docker 模式下返回有效的 DockerManager。
|
||||
/// 如果需要同时支持 Docker 和 K8s,请使用 get_global_runtime()
|
||||
///
|
||||
/// 如果未初始化,会自动初始化
|
||||
pub async fn get_global_docker_manager() -> DockerResult<Arc<DockerManager>> {
|
||||
#[cfg(feature = "kubernetes")]
|
||||
if RuntimeType::from_env() == RuntimeType::Kubernetes {
|
||||
return Err(DockerError::ConfigurationError(
|
||||
"DockerManager is unavailable in Kubernetes runtime mode. Use RuntimeManager::get()"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if GLOBAL_DOCKER_MANAGER.get().is_none() {
|
||||
debug!("DockerManager not initialized, starting initialize");
|
||||
init_global_docker_manager().await?;
|
||||
}
|
||||
|
||||
GLOBAL_DOCKER_MANAGER.get().cloned().ok_or_else(|| {
|
||||
DockerError::IoError(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
"unable to get global DockerManager",
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
/// 使用全局 DockerManager 执行操作(向后兼容)
|
||||
pub async fn with_global_docker_manager<F, R>(f: F) -> DockerResult<R>
|
||||
where
|
||||
F: FnOnce(&Arc<DockerManager>) -> R,
|
||||
{
|
||||
let manager = get_global_docker_manager().await?;
|
||||
Ok(f(&manager))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user