From 7cbe9361dbcea18a6ba4014a0e0e069258161b15 Mon Sep 17 00:00:00 2001 From: DoL <145818730+dolzhuying@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:12:45 +0800 Subject: [PATCH] feat(provider): add add get_function_list to route (#77) * feat(namespace):replace netns_map's key with (string,string) so that key (cid,ns) refers to the only net work * fix:fix the error response in proxy_handler * feat:add get_function_list to route * feat:replace map's key (string,string) with struct --- crates/app/src/main.rs | 8 ++- crates/provider/src/handlers/function_get.rs | 8 ++- crates/provider/src/handlers/function_list.rs | 57 ++++++++++++++++++- .../provider/src/handlers/invoke_resolver.rs | 10 ++-- crates/provider/src/proxy/proxy_handler.rs | 2 +- crates/service/src/containerd_manager.rs | 29 +++++++--- crates/service/src/lib.rs | 8 ++- 7 files changed, 102 insertions(+), 20 deletions(-) diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index fb0bce7..cef0385 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,6 +1,8 @@ use actix_web::{App, HttpServer, web}; use provider::{ - handlers::{delete::delete_handler, deploy::deploy_handler}, + handlers::{ + delete::delete_handler, deploy::deploy_handler, function_list::function_list_handler, + }, proxy::proxy_handler::proxy_handler, types::config::FaaSConfig, }; @@ -24,6 +26,10 @@ async fn main() -> std::io::Result<()> { .route("/system/functions", web::post().to(deploy_handler)) .route("/system/functions", web::delete().to(delete_handler)) .route("/function/{name}{path:/?.*}", web::to(proxy_handler)) + .route( + "/system/functions/{namespace}", + web::get().to(function_list_handler), + ) // 更多路由配置... }) .bind("0.0.0.0:8090")?; diff --git a/crates/provider/src/handlers/function_get.rs b/crates/provider/src/handlers/function_get.rs index b91e559..4cc8e54 100644 --- a/crates/provider/src/handlers/function_get.rs +++ b/crates/provider/src/handlers/function_get.rs @@ -1,7 +1,7 @@ use crate::handlers::function_list::Function; // use service::spec::{ Mount, Spec}; use actix_web::cookie::time::Duration; -use service::{containerd_manager::ContainerdManager, image_manager::ImageManager}; +use service::{FunctionScope, containerd_manager::ContainerdManager, image_manager::ImageManager}; use std::{collections::HashMap, time::UNIX_EPOCH}; use thiserror::Error; @@ -23,7 +23,11 @@ impl From> for FunctionError { pub async fn get_function(function_name: &str, namespace: &str) -> Result { let cid = function_name; - let address = ContainerdManager::get_address(cid); + let function = FunctionScope { + function_name: cid.to_string(), + namespace: namespace.to_string(), + }; + let address = ContainerdManager::get_address(&function); let container = ContainerdManager::load_container(cid, namespace) .await diff --git a/crates/provider/src/handlers/function_list.rs b/crates/provider/src/handlers/function_list.rs index ec89ae9..397e0bf 100644 --- a/crates/provider/src/handlers/function_list.rs +++ b/crates/provider/src/handlers/function_list.rs @@ -1,6 +1,12 @@ use std::{collections::HashMap, time::SystemTime}; -#[derive(Debug)] +use actix_web::{HttpRequest, HttpResponse, Responder}; +use serde::{Deserialize, Serialize}; +use service::containerd_manager::ContainerdManager; + +use super::{function_get::get_function, utils::CustomError}; + +#[derive(Debug, Serialize, Deserialize)] pub struct Function { pub name: String, pub namespace: String, @@ -16,3 +22,52 @@ pub struct Function { // pub memory_limit: i64, pub created_at: SystemTime, } + +pub async fn function_list_handler(req: HttpRequest) -> impl Responder { + let namespace = req.match_info().get("namespace").unwrap_or(""); + if namespace.is_empty() { + return HttpResponse::BadRequest().body("provide namespace in path"); + } + match get_function_list(namespace).await { + Ok(functions) => HttpResponse::Ok().body(serde_json::to_string(&functions).unwrap()), + Err(e) => HttpResponse::from_error(e), + } +} + +async fn get_function_list(namespace: &str) -> Result, CustomError> { + let namespaces = match ContainerdManager::list_namespaces().await { + Ok(namespace) => namespace, + Err(e) => { + return Err(CustomError::OtherError(format!( + "Failed to list namespaces:{}", + e + ))); + } + }; + if !namespaces.contains(&namespace.to_string()) { + return Err(CustomError::OtherError(format!( + "Namespace '{}' not valid or does not exist", + namespace + ))); + } + let container_list = match ContainerdManager::list_container_into_string(namespace).await { + Ok(container_list) => container_list, + Err(e) => { + return Err(CustomError::OtherError(format!( + "Failed to list container:{}", + e + ))); + } + }; + log::info!("container_list: {:?}", container_list); + let mut functions: Vec = Vec::new(); + for cid in container_list { + log::info!("cid: {}", cid); + let function = match get_function(&cid, namespace).await { + Ok(function) => function, + Err(e) => return Err(CustomError::FunctionError(e)), + }; + functions.push(function); + } + Ok(functions) +} diff --git a/crates/provider/src/handlers/invoke_resolver.rs b/crates/provider/src/handlers/invoke_resolver.rs index 4c08e95..957d7e4 100644 --- a/crates/provider/src/handlers/invoke_resolver.rs +++ b/crates/provider/src/handlers/invoke_resolver.rs @@ -12,13 +12,13 @@ impl InvokeResolver { //根据函数名和containerd获取函数ip, //从函数名称中提取命名空间。如果函数名称中包含 .,则将其后的部分作为命名空间;否则使用默认命名空间 - // let mut actual_function_name = function_name; + let mut actual_function_name = function_name; let namespace = get_namespace_or_default(function_name, DEFAULT_FUNCTION_NAMESPACE); - // if function_name.contains('.') { - // actual_function_name = function_name.trim_end_matches(&format!(".{}", namespace)); - // } + if function_name.contains('.') { + actual_function_name = function_name.trim_end_matches(&format!(".{}", namespace)); + } - let function = match get_function(function_name, &namespace).await { + let function = match get_function(actual_function_name, &namespace).await { Ok(function) => function, Err(e) => { log::error!("Failed to get function:{}", e); diff --git a/crates/provider/src/proxy/proxy_handler.rs b/crates/provider/src/proxy/proxy_handler.rs index 7828905..abcb7cd 100644 --- a/crates/provider/src/proxy/proxy_handler.rs +++ b/crates/provider/src/proxy/proxy_handler.rs @@ -24,7 +24,7 @@ pub async fn proxy_handler( | Method::HEAD | Method::OPTIONS => match proxy_request(&req, payload, &proxy_client).await { Ok(resp) => resp, - Err(e) => HttpResponse::InternalServerError().body(e.to_string()), + Err(e) => HttpResponse::from_error(e), }, _ => HttpResponse::MethodNotAllowed().body("method not allowed"), } diff --git a/crates/service/src/containerd_manager.rs b/crates/service/src/containerd_manager.rs index 794006d..405f610 100644 --- a/crates/service/src/containerd_manager.rs +++ b/crates/service/src/containerd_manager.rs @@ -20,7 +20,10 @@ use tokio::{ time::{Duration, timeout}, }; -use crate::{GLOBAL_NETNS_MAP, NetworkConfig, image_manager::ImageManager, spec::generate_spec}; +use crate::{ + FunctionScope, GLOBAL_NETNS_MAP, NetworkConfig, image_manager::ImageManager, + spec::generate_spec, +}; pub(super) static CLIENT: OnceCell> = OnceCell::const_new(); @@ -474,31 +477,39 @@ impl ContainerdManager { })?; let ports = ImageManager::get_runtime_config(image_name).unwrap().ports; let network_config = NetworkConfig::new(ip, ports); - Self::save_container_network_config(cid, network_config); + let function = FunctionScope { + function_name: cid.to_string(), + namespace: ns.to_string(), + }; + Self::save_container_network_config(function, network_config); Ok(()) } /// 删除cni网络,删除全局map中的网络配置 fn remove_cni_network(cid: &str, ns: &str) -> Result<(), ContainerdError> { cni::delete_cni_network(ns, cid); - Self::remove_container_network_config(cid); + let function = FunctionScope { + function_name: cid.to_string(), + namespace: ns.to_string(), + }; + Self::remove_container_network_config(&function); Ok(()) } - fn save_container_network_config(cid: &str, net_conf: NetworkConfig) { + fn save_container_network_config(function: FunctionScope, net_conf: NetworkConfig) { let mut map = GLOBAL_NETNS_MAP.write().unwrap(); - map.insert(cid.to_string(), net_conf); + map.insert(function, net_conf); } - pub fn get_address(cid: &str) -> String { + pub fn get_address(function: &FunctionScope) -> String { let map = GLOBAL_NETNS_MAP.read().unwrap(); - let addr = map.get(cid).map(|net_conf| net_conf.get_address()); + let addr = map.get(function).map(|net_conf| net_conf.get_address()); addr.unwrap_or_default() } - fn remove_container_network_config(cid: &str) { + fn remove_container_network_config(function: &FunctionScope) { let mut map = GLOBAL_NETNS_MAP.write().unwrap(); - map.remove(cid); + map.remove(function); } pub async fn list_namespaces() -> Result, ContainerdError> { diff --git a/crates/service/src/lib.rs b/crates/service/src/lib.rs index 1ad2d69..cf64e36 100644 --- a/crates/service/src/lib.rs +++ b/crates/service/src/lib.rs @@ -11,11 +11,17 @@ use std::{ // config.json,dockerhub密钥 // const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/"; -type NetnsMap = Arc>>; +type NetnsMap = Arc>>; lazy_static::lazy_static! { static ref GLOBAL_NETNS_MAP: NetnsMap = Arc::new(RwLock::new(HashMap::new())); } +#[derive(Hash, Eq, PartialEq)] +pub struct FunctionScope { + pub function_name: String, + pub namespace: String, +} + #[derive(Debug, Clone)] pub struct NetworkConfig { ip: String,