Samuel Dai 308e9bcc5d
refactor: project structure and better interfaces (#100)
* refactor: basically rewrite all interface

* refactor: rename crates to make clear meaning; use tokio runtime and handle shutdown within Provider

* remove tracker in main

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* feat(provider): enhance Provider trait with list, update, and status methods; refactor existing methods to async

* fix(containerd): fetch handle from environment and initialize it.

* fix(init): BACKEND init add handle fetching

* fix: add test framework

* fix: move the snapshot logic into snapshot.rs

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: change some spec setting

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* feat: add created_at field, add http status code convertion

* refactor(spec): use builder to generate spec

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: clippy

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* manage reference, fix boot issue

* fix: ip parsing

* feat: add cleanup logic on fail

* fix style: clippy for return function

* feat: add response message

* fix:1.修复proxy和resolve的逻辑 2.spec内netns的路径问题以及传参顺序

* feat:add update list status  service implmentation

* fix: move some consts into consts.rs

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: fmt & clippy

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix: update dependecy

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* feat: add function with_vm_network

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* feat: integrate cni into containerd crate

* fix:修复proxy的路径正则匹配并添加单元测试

* fix:fix proxy_path and add default namespace for Query::from

* fix: integration_test

* fix: path dispatch test

* fix: more specified url dispatch in proxy handle

* feat: add persistent container record for restart service

* feat: add task error type

* fix: delete error handle logic

---------

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Co-authored-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Co-authored-by: dolzhuying <1240800466@qq.com>
Co-authored-by: scutKKsix <1129332011@qq.com>
2025-05-22 21:43:16 +08:00

151 lines
6.0 KiB
Rust

use actix_web::App;
use actix_web::http::StatusCode;
use actix_web::test;
use faas_containerd::consts::DEFAULT_FAASDRS_DATA_DIR;
use gateway::bootstrap::config_app;
use serde_json::json;
#[actix_web::test]
#[ignore]
async fn test_handlers_in_order() {
dotenv::dotenv().ok();
faas_containerd::init_backend().await;
let provider = faas_containerd::provider::ContainerdProvider::new(DEFAULT_FAASDRS_DATA_DIR);
let app = test::init_service(App::new().configure(config_app(provider))).await;
// test proxy no-found-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::get()
.uri("/function/test-no-found-function")
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
assert!(response_str.contains("Invalid function name"));
// test update no-found-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::put()
.uri("/system/functions")
.set_json(json!({
"service": "test-no-found-function",
"image": "hub.scutosc.cn/dolzhuying/echo:latest",
"namespace": "faasrs-test-namespace"
}))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
assert!(response_str.contains("NotFound: container not found"));
// test delete no-found-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::delete()
.uri("/system/functions")
.set_json(json!({
"functionName": "test-no-found-function",
"namespace": "faasrs-test-namespace"
}))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
// test deploy test-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::post()
.uri("/system/functions")
.set_json(json!({
"service": "test-function",
"image": "hub.scutosc.cn/dolzhuying/echo:latest",
"namespace": "faasrs-test-namespace"
}))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(
resp.status(),
StatusCode::ACCEPTED,
"error: {:?}",
resp.response()
);
// test update test-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::put()
.uri("/system/functions")
.set_json(json!({
"service": "test-function",
"image": "hub.scutosc.cn/dolzhuying/echo:latest",
"namespace": "faasrs-test-namespace"
}))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::ACCEPTED);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
assert!(response_str.contains("function test-function was updated successfully"));
// test list
let req = test::TestRequest::get()
.uri("/system/functions?namespace=faasrs-test-namespace")
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
let response_json: serde_json::Value = serde_json::from_str(response_str).unwrap();
if let Some(arr) = response_json.as_array() {
for item in arr {
assert_eq!(
item["name"],
serde_json::Value::String("test-function".to_string())
);
assert_eq!(
item["image"],
serde_json::Value::String("hub.scutosc.cn/dolzhuying/echo:latest".to_string())
);
assert_eq!(
item["namespace"],
serde_json::Value::String("faasrs-test-namespace".to_string())
);
}
}
// test status test-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::get()
.uri("/system/function/test-function?namespace=faasrs-test-namespace")
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
let response_json: serde_json::Value = serde_json::from_str(response_str).unwrap();
if let Some(arr) = response_json.as_array() {
for item in arr {
assert_eq!(item["name"], "test-function");
assert_eq!(item["image"], "hub.scutosc.cn/dolzhuying/echo:latest");
assert_eq!(item["namespace"], "faasrs-test-namespace");
}
}
// test proxy test-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::get()
.uri("/function/test-function.faasrs-test-namespace")
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
assert!(response_str.contains("Hello world!"));
// test delete test-function in namespace 'faasrs-test-namespace'
let req = test::TestRequest::delete()
.uri("/system/functions")
.set_json(json!({
"functionName": "test-function",
"namespace": "faasrs-test-namespace"
}))
.to_request();
let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let response_body = test::read_body(resp).await;
let response_str = std::str::from_utf8(&response_body).unwrap();
assert!(response_str.contains("function test-function was deleted successfully"));
}