feat:gateway-mvp implmentation,enable to deploy function,proxy request to the container and delete function's container and task

This commit is contained in:
dolzhuying 2025-04-12 13:26:13 +08:00 committed by Samuel Dai
parent 7258f4f6ed
commit 92b281dc48
8 changed files with 35 additions and 23 deletions

View File

@ -8,8 +8,9 @@ pub mod types;
use handlers::*; use handlers::*;
use provider::{ use provider::{
handlers::{delete::delete_handler, deploy::deploy_handler}, handlers::{delete::delete_handler, deploy::deploy_handler, invoke_resolver::InvokeResolver},
proxy::proxy_handler::proxy_handler, proxy::proxy_handler::proxy_handler,
types::config::FaaSConfig,
}; };
#[actix_web::main] #[actix_web::main]
@ -21,11 +22,16 @@ async fn main() -> std::io::Result<()> {
.unwrap(), .unwrap(),
); );
let resolver = Some(InvokeResolver::new(service.clone()).await);
let faas_config = FaaSConfig::new();
println!("I'm running!"); println!("I'm running!");
let server = HttpServer::new(move || { let server = HttpServer::new(move || {
App::new() App::new()
.app_data(web::Data::new(service.clone())) .app_data(web::Data::new(service.clone()))
.app_data(web::Data::new(resolver.clone()))
.app_data(web::Data::new(faas_config.clone()))
.route("/create-container", web::post().to(create_container)) .route("/create-container", web::post().to(create_container))
.route("/remove-container", web::post().to(remove_container)) .route("/remove-container", web::post().to(remove_container))
.route("/containers", web::get().to(get_container_list)) .route("/containers", web::get().to(get_container_list))

View File

@ -5,7 +5,7 @@ use crate::{
utils::{CustomError, map_service_error}, utils::{CustomError, map_service_error},
}, },
}; };
use actix_web::{HttpResponse, Responder, error, web}; use actix_web::{HttpResponse, Responder, ResponseError, error, web};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use service::Service; use service::Service;
use std::sync::Arc; use std::sync::Arc;
@ -24,10 +24,7 @@ pub async fn delete_handler(
Ok(()) => { Ok(()) => {
HttpResponse::Ok().body(format!("function {} deleted successfully", function_name)) HttpResponse::Ok().body(format!("function {} deleted successfully", function_name))
} }
Err(e) => HttpResponse::InternalServerError().body(format!( Err(e) => e.error_response(),
"failed to delete function {} in namespace {} because {}",
function_name, namespace, e
)),
} }
} }

View File

@ -1,7 +1,8 @@
use crate::handlers::function_list::Function; use crate::handlers::function_list::Function;
// use service::spec::{ Mount, Spec}; // use service::spec::{ Mount, Spec};
use actix_web::cookie::time::Duration; use actix_web::cookie::time::Duration;
use std::{collections::HashMap, time::UNIX_EPOCH}; use service::Service;
use std::{collections::HashMap, sync::Arc, time::UNIX_EPOCH};
use thiserror::Error; use thiserror::Error;
const ANNOTATION_LABEL_PREFIX: &str = "com.openfaas.annotations."; const ANNOTATION_LABEL_PREFIX: &str = "com.openfaas.annotations.";
@ -21,14 +22,14 @@ impl From<Box<dyn std::error::Error>> for FunctionError {
} }
pub async fn get_function( pub async fn get_function(
client: &service::Service, service: &Arc<Service>,
function_name: &str, function_name: &str,
namespace: &str, namespace: &str,
) -> Result<Function, FunctionError> { ) -> Result<Function, FunctionError> {
let cid = function_name; let cid = function_name;
let ip = client.get_ip(cid).await.unwrap(); let ip = client.get_ip(cid).await.unwrap();
let container = client let container = service
.load_container(cid, namespace) .load_container(cid, namespace)
.await .await
.map_err(|e| FunctionError::FunctionNotFound(e.to_string()))?; .map_err(|e| FunctionError::FunctionNotFound(e.to_string()))?;
@ -50,7 +51,7 @@ pub async fn get_function(
let timestamp = container.created_at.unwrap_or_default(); let timestamp = container.created_at.unwrap_or_default();
let created_at = UNIX_EPOCH + Duration::new(timestamp.seconds, timestamp.nanos); let created_at = UNIX_EPOCH + Duration::new(timestamp.seconds, timestamp.nanos);
let task = client let task = service
.get_task(cid, namespace) .get_task(cid, namespace)
.await .await
.map_err(|e| FunctionError::FunctionNotFound(e.to_string())); .map_err(|e| FunctionError::FunctionNotFound(e.to_string()));

View File

@ -1,5 +1,6 @@
use std::{collections::HashMap, time::SystemTime}; use std::{collections::HashMap, time::SystemTime};
#[derive(Debug)]
pub struct Function { pub struct Function {
pub name: String, pub name: String,
pub namespace: String, pub namespace: String,

View File

@ -2,14 +2,17 @@ use crate::consts::DEFAULT_FUNCTION_NAMESPACE;
use crate::handlers::function_get::get_function; use crate::handlers::function_get::get_function;
use actix_web::{Error, error::ErrorInternalServerError}; use actix_web::{Error, error::ErrorInternalServerError};
use log; use log;
use service::Service;
use std::sync::Arc;
use url::Url; use url::Url;
#[derive(Clone)]
pub struct InvokeResolver { pub struct InvokeResolver {
client: service::Service, client: Arc<Service>,
} }
impl InvokeResolver { impl InvokeResolver {
pub async fn new(client: service::Service) -> Self { pub async fn new(client: Arc<Service>) -> Self {
Self { client } Self { client }
} }
@ -17,13 +20,13 @@ impl InvokeResolver {
//根据函数名和containerd获取函数ip //根据函数名和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); let namespace = get_namespace_or_default(function_name, DEFAULT_FUNCTION_NAMESPACE);
if function_name.contains('.') { // if function_name.contains('.') {
actual_function_name = function_name.trim_end_matches(&format!(".{}", namespace)); // actual_function_name = function_name.trim_end_matches(&format!(".{}", namespace));
} // }
let function = match get_function(&self.client, actual_function_name, &namespace).await { let function = match get_function(&self.client, function_name, &namespace).await {
Ok(function) => function, Ok(function) => function,
Err(e) => { Err(e) => {
log::error!("Failed to get function:{}", e); log::error!("Failed to get function:{}", e);
@ -31,10 +34,12 @@ impl InvokeResolver {
} }
}; };
let ip = function.ip; //容器启动后的port?
let port = 8080; let ip = function.ip.clone();
println!("function: {:?}", function);
//let port = 80;
let urlstr = format!("http://{}:{}", ip, port); let urlstr = format!("http://{}", ip);
match Url::parse(&urlstr) { match Url::parse(&urlstr) {
Ok(url) => Ok(url), Ok(url) => Ok(url),
Err(e) => { Err(e) => {

View File

@ -19,6 +19,7 @@ pub async fn proxy_handler(
.expect("empty proxy handler resolver, cannot be nil"); .expect("empty proxy handler resolver, cannot be nil");
let proxy_client = new_proxy_client_from_config(config.as_ref()).await; let proxy_client = new_proxy_client_from_config(config.as_ref()).await;
println!("proxy_client : {:?}", proxy_client);
match *req.method() { match *req.method() {
Method::POST Method::POST

View File

@ -25,13 +25,13 @@ impl FaaSConfig {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
tcp_port: None, tcp_port: None,
read_timeout: Duration::from_secs(0), read_timeout: Duration::from_secs(10),
write_timeout: Duration::from_secs(0), write_timeout: Duration::from_secs(10),
enable_health: false, enable_health: false,
enable_basic_auth: false, enable_basic_auth: false,
secret_mount_path: String::from("/var/openfaas/secrets"), secret_mount_path: String::from("/var/openfaas/secrets"),
max_idle_conns: 0, max_idle_conns: 0,
max_idle_conns_per_host: 0, max_idle_conns_per_host: 10,
} }
} }
pub fn get_read_timeout(&self) -> Duration { pub fn get_read_timeout(&self) -> Duration {

View File

@ -177,6 +177,7 @@ impl Service {
// TASK_EXITED (4) — 任务已退出 // TASK_EXITED (4) — 任务已退出
// TASK_PAUSED (5) — 任务已暂停 // TASK_PAUSED (5) — 任务已暂停
// TASK_FAILED (6) — 任务失败 // TASK_FAILED (6) — 任务失败
let _ = self.kill_task(task.id.to_string(), ns).await;
let _ = self.delete_task(&task.id, ns).await; let _ = self.delete_task(&task.id, ns).await;
} }