mirror of
https://github.com/faas-rs/faasd-in-rust.git
synced 2025-06-08 07:55:04 +00:00
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
This commit is contained in:
parent
9277d3ef0b
commit
7cbe9361db
@ -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")?;
|
||||
|
@ -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<Box<dyn std::error::Error>> for FunctionError {
|
||||
|
||||
pub async fn get_function(function_name: &str, namespace: &str) -> Result<Function, FunctionError> {
|
||||
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
|
||||
|
@ -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<Vec<Function>, 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<Function> = 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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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"),
|
||||
}
|
||||
|
@ -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<Arc<Client>> = 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<Vec<String>, ContainerdError> {
|
||||
|
@ -11,11 +11,17 @@ use std::{
|
||||
// config.json,dockerhub密钥
|
||||
// const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/";
|
||||
|
||||
type NetnsMap = Arc<RwLock<HashMap<String, NetworkConfig>>>;
|
||||
type NetnsMap = Arc<RwLock<HashMap<FunctionScope, NetworkConfig>>>;
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user