mirror of
https://github.com/faas-rs/faasd-in-rust.git
synced 2025-06-08 15:56:48 +00:00
commit
bc54e9c2d0
186
Cargo.lock
generated
186
Cargo.lock
generated
@ -491,6 +491,41 @@ dependencies = [
|
|||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deranged"
|
name = "deranged"
|
||||||
version = "0.3.11"
|
version = "0.3.11"
|
||||||
@ -500,6 +535,37 @@ dependencies = [
|
|||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_core"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_macro"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_core",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.18"
|
version = "0.99.18"
|
||||||
@ -687,6 +753,18 @@ dependencies = [
|
|||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getset"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eded738faa0e88d3abc9d1a13cb11adc2073c400969eeb8793cf7132589959fc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.1"
|
version = "0.31.1"
|
||||||
@ -755,6 +833,12 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "http"
|
name = "http"
|
||||||
version = "0.2.12"
|
version = "0.2.12"
|
||||||
@ -989,6 +1073,12 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@ -1210,6 +1300,21 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "oci-spec"
|
||||||
|
version = "0.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bdf88ddc01cc6bccbe1044adb6a29057333f523deadcb4953c011a73158cfa5e"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder",
|
||||||
|
"getset",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"strum",
|
||||||
|
"strum_macros",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.20.2"
|
version = "1.20.2"
|
||||||
@ -1324,6 +1429,28 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error2"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr2",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.93"
|
||||||
@ -1570,11 +1697,14 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"containerd-client",
|
"containerd-client",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"hex",
|
||||||
"log",
|
"log",
|
||||||
"my-workspace-hack",
|
"my-workspace-hack",
|
||||||
|
"oci-spec",
|
||||||
"prost-types",
|
"prost-types",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tonic",
|
"tonic",
|
||||||
]
|
]
|
||||||
@ -1590,6 +1720,17 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@ -1636,6 +1777,31 @@ version = "1.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.26.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.26.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.96"
|
version = "2.0.96"
|
||||||
@ -1687,6 +1853,26 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.37"
|
version = "0.3.37"
|
||||||
|
@ -10,7 +10,8 @@ pub async fn create_container(
|
|||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let cid = info.container_id.clone();
|
let cid = info.container_id.clone();
|
||||||
let image = info.image.clone();
|
let image = info.image.clone();
|
||||||
service.create_container(image, cid).await;
|
let ns = info.ns.clone();
|
||||||
|
service.create_container(&image, &cid, &ns).await.unwrap();
|
||||||
HttpResponse::Ok().json("Container created successfully!")
|
HttpResponse::Ok().json("Container created successfully!")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,12 +21,18 @@ pub async fn remove_container(
|
|||||||
info: web::Json<RemoveContainerInfo>,
|
info: web::Json<RemoveContainerInfo>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let container_id = info.container_id.clone();
|
let container_id = info.container_id.clone();
|
||||||
service.remove_container(container_id).await;
|
let ns = info.ns.clone();
|
||||||
|
service.remove_container(&container_id, &ns).await.unwrap();
|
||||||
HttpResponse::Ok().json("Container removed successfully!")
|
HttpResponse::Ok().json("Container removed successfully!")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_container_list(service: web::Data<Arc<Service>>) -> impl Responder {
|
/// 获取容器列表
|
||||||
let container_list = service.get_container_list().await.unwrap();
|
pub async fn get_container_list(
|
||||||
|
service: web::Data<Arc<Service>>,
|
||||||
|
info: web::Json<GetContainerListQuery>,
|
||||||
|
) -> impl Responder {
|
||||||
|
let ns = info.ns.clone();
|
||||||
|
let container_list = service.get_container_list(&ns).await.unwrap();
|
||||||
HttpResponse::Ok().json(container_list)
|
HttpResponse::Ok().json(container_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,17 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub struct CreateContainerInfo {
|
pub struct CreateContainerInfo {
|
||||||
pub container_id: String,
|
pub container_id: String,
|
||||||
pub image: String,
|
pub image: String,
|
||||||
|
pub ns: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct RemoveContainerInfo {
|
pub struct RemoveContainerInfo {
|
||||||
pub container_id: String,
|
pub container_id: String,
|
||||||
|
pub ns: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetContainerListQuery {
|
pub struct GetContainerListQuery {
|
||||||
pub status: Option<String>,
|
pub status: Option<String>,
|
||||||
|
pub ns: String,
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,7 @@ serde_json = "1.0"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
prost-types = "0.13.4"
|
prost-types = "0.13.4"
|
||||||
|
oci-spec = "0.6"
|
||||||
|
sha2 = "0.10"
|
||||||
|
hex = "0.4"
|
||||||
my-workspace-hack = { version = "0.1", path = "../my-workspace-hack" }
|
my-workspace-hack = { version = "0.1", path = "../my-workspace-hack" }
|
||||||
|
@ -1,290 +0,0 @@
|
|||||||
|
|
||||||
{
|
|
||||||
"ID": "hello",
|
|
||||||
"Labels": {
|
|
||||||
"io.containerd.image.config.stop-signal": "SIGTERM"
|
|
||||||
},
|
|
||||||
"Image": "docker.io/library/hello-world:latest",
|
|
||||||
"Runtime": {
|
|
||||||
"Name": "io.containerd.runc.v2",
|
|
||||||
"Options": {
|
|
||||||
"type_url": "containerd.runc.v1.Options"
|
|
||||||
}susu
|
|
||||||
},
|
|
||||||
"SnapshotKey": "hello",
|
|
||||||
"Snapshotter": "overlayfs",
|
|
||||||
"CreatedAt": "2025-01-25T10:08:43.259272017Z",
|
|
||||||
"UpdatedAt": "2025-01-25T10:08:43.259272017Z",
|
|
||||||
"Extensions": {},
|
|
||||||
"SandboxID": "",
|
|
||||||
"Spec": {
|
|
||||||
"ociVersion": "1.1.0",
|
|
||||||
"process": {
|
|
||||||
"user": {
|
|
||||||
"uid": 0,
|
|
||||||
"gid": 0,
|
|
||||||
"additionalGids": [
|
|
||||||
0
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"/hello"
|
|
||||||
],
|
|
||||||
"env": [
|
|
||||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
||||||
],
|
|
||||||
"cwd": "/",
|
|
||||||
"capabilities": {
|
|
||||||
"bounding": [
|
|
||||||
"CAP_CHOWN",
|
|
||||||
"CAP_DAC_OVERRIDE",
|
|
||||||
"CAP_FSETID",
|
|
||||||
"CAP_FOWNER",
|
|
||||||
"CAP_MKNOD",
|
|
||||||
"CAP_NET_RAW",
|
|
||||||
"CAP_SETGID",
|
|
||||||
"CAP_SETUID",
|
|
||||||
"CAP_SETFCAP",
|
|
||||||
"CAP_SETPCAP",
|
|
||||||
"CAP_NET_BIND_SERVICE",
|
|
||||||
"CAP_SYS_CHROOT",
|
|
||||||
"CAP_KILL",
|
|
||||||
"CAP_AUDIT_WRITE"
|
|
||||||
],
|
|
||||||
"effective": [
|
|
||||||
"CAP_CHOWN",
|
|
||||||
"CAP_DAC_OVERRIDE",
|
|
||||||
"CAP_FSETID",
|
|
||||||
"CAP_FOWNER",
|
|
||||||
"CAP_MKNOD",
|
|
||||||
"CAP_NET_RAW",
|
|
||||||
"CAP_SETGID",
|
|
||||||
"CAP_SETUID",
|
|
||||||
"CAP_SETFCAP",
|
|
||||||
"CAP_SETPCAP",
|
|
||||||
"CAP_NET_BIND_SERVICE",
|
|
||||||
"CAP_SYS_CHROOT",
|
|
||||||
"CAP_KILL",
|
|
||||||
"CAP_AUDIT_WRITE"
|
|
||||||
],
|
|
||||||
"permitted": [
|
|
||||||
"CAP_CHOWN",
|
|
||||||
"CAP_DAC_OVERRIDE",
|
|
||||||
"CAP_FSETID",
|
|
||||||
"CAP_FOWNER",
|
|
||||||
"CAP_MKNOD",
|
|
||||||
"CAP_NET_RAW",
|
|
||||||
"CAP_SETGID",
|
|
||||||
"CAP_SETUID",
|
|
||||||
"CAP_SETFCAP",
|
|
||||||
"CAP_SETPCAP",
|
|
||||||
"CAP_NET_BIND_SERVICE",
|
|
||||||
"CAP_SYS_CHROOT",
|
|
||||||
"CAP_KILL",
|
|
||||||
"CAP_AUDIT_WRITE"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rlimits": [
|
|
||||||
{
|
|
||||||
"type": "RLIMIT_NOFILE",
|
|
||||||
"hard": 1024,
|
|
||||||
"soft": 1024
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noNewPrivileges": true
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"path": "rootfs"
|
|
||||||
},
|
|
||||||
"mounts": [
|
|
||||||
{
|
|
||||||
"destination": "/proc",
|
|
||||||
"type": "proc",
|
|
||||||
"source": "proc",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"noexec",
|
|
||||||
"nodev"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/dev",
|
|
||||||
"type": "tmpfs",
|
|
||||||
"source": "tmpfs",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"strictatime",
|
|
||||||
"mode=755",
|
|
||||||
"size=65536k"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/dev/pts",
|
|
||||||
"type": "devpts",
|
|
||||||
"source": "devpts",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"noexec",
|
|
||||||
"newinstance",
|
|
||||||
"ptmxmode=0666",
|
|
||||||
"mode=0620",
|
|
||||||
"gid=5"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/dev/shm",
|
|
||||||
"type": "tmpfs",
|
|
||||||
"source": "shm",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"noexec",
|
|
||||||
"nodev",
|
|
||||||
"mode=1777",
|
|
||||||
"size=65536k"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/dev/mqueue",
|
|
||||||
"type": "mqueue",
|
|
||||||
"source": "mqueue",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"noexec",
|
|
||||||
"nodev"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/sys",
|
|
||||||
"type": "sysfs",
|
|
||||||
"source": "sysfs",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"noexec",
|
|
||||||
"nodev",
|
|
||||||
"ro"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"destination": "/run",
|
|
||||||
"type": "tmpfs",
|
|
||||||
"source": "tmpfs",
|
|
||||||
"options": [
|
|
||||||
"nosuid",
|
|
||||||
"strictatime",
|
|
||||||
"mode=755",
|
|
||||||
"size=65536k"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"linux": {
|
|
||||||
"resources": {
|
|
||||||
"devices": [
|
|
||||||
{
|
|
||||||
"allow": false,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 1,
|
|
||||||
"minor": 3,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 1,
|
|
||||||
"minor": 8,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 1,
|
|
||||||
"minor": 7,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 5,
|
|
||||||
"minor": 0,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 1,
|
|
||||||
"minor": 5,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 1,
|
|
||||||
"minor": 9,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 5,
|
|
||||||
"minor": 1,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 136,
|
|
||||||
"access": "rwm"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow": true,
|
|
||||||
"type": "c",
|
|
||||||
"major": 5,
|
|
||||||
"minor": 2,
|
|
||||||
"access": "rwm"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"cgroupsPath": "/default/hello",
|
|
||||||
"namespaces": [
|
|
||||||
{
|
|
||||||
"type": "pid"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "ipc"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "uts"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "mount"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "network"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"maskedPaths": [
|
|
||||||
"/proc/acpi",
|
|
||||||
"/proc/asound",
|
|
||||||
"/proc/kcore",
|
|
||||||
"/proc/keys",
|
|
||||||
"/proc/latency_stats",
|
|
||||||
"/proc/timer_list",
|
|
||||||
"/proc/timer_stats",
|
|
||||||
"/proc/sched_debug",
|
|
||||||
"/sys/firmware",
|
|
||||||
"/sys/devices/virtual/powercap",
|
|
||||||
"/proc/scsi"
|
|
||||||
],
|
|
||||||
"readonlyPaths": [
|
|
||||||
"/proc/bus",
|
|
||||||
"/proc/fs",
|
|
||||||
"/proc/irq",
|
|
||||||
"/proc/sys",
|
|
||||||
"/proc/sysrq-trigger"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +1,24 @@
|
|||||||
|
pub mod spec;
|
||||||
|
|
||||||
use containerd_client::{
|
use containerd_client::{
|
||||||
Client,
|
Client,
|
||||||
services::v1::{
|
services::v1::{
|
||||||
Container, CreateContainerRequest, CreateTaskRequest, DeleteContainerRequest,
|
Container, CreateContainerRequest, CreateTaskRequest, DeleteContainerRequest,
|
||||||
DeleteTaskRequest, KillRequest, ListContainersRequest, ListTasksRequest, StartRequest,
|
DeleteTaskRequest, GetImageRequest, KillRequest, ListContainersRequest, ListTasksRequest,
|
||||||
WaitRequest, container::Runtime,
|
ReadContentRequest, StartRequest, WaitRequest,
|
||||||
|
container::Runtime,
|
||||||
|
snapshots::{MountsRequest, PrepareSnapshotRequest},
|
||||||
},
|
},
|
||||||
tonic::Request,
|
tonic::Request,
|
||||||
|
types::Mount,
|
||||||
with_namespace,
|
with_namespace,
|
||||||
};
|
};
|
||||||
|
use oci_spec::image::{Arch, ImageConfiguration, ImageIndex, ImageManifest, MediaType, Os};
|
||||||
|
use prost_types::Any;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
use spec::generate_spec;
|
||||||
use std::{
|
use std::{
|
||||||
fs::{self, File},
|
fs,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@ -18,7 +26,6 @@ use tokio::time::timeout;
|
|||||||
|
|
||||||
// config.json,dockerhub密钥
|
// config.json,dockerhub密钥
|
||||||
// const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/";
|
// const DOCKER_CONFIG_DIR: &str = "/var/lib/faasd/.docker/";
|
||||||
|
|
||||||
// 命名空间(容器的)
|
// 命名空间(容器的)
|
||||||
const NAMESPACE: &str = "default";
|
const NAMESPACE: &str = "default";
|
||||||
|
|
||||||
@ -36,21 +43,54 @@ impl Service {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_container(&self, image: String, cid: String) {
|
async fn prepare_snapshot(&self, cid: &str, ns: &str) -> Result<Vec<Mount>, Err> {
|
||||||
// let spec = include_str!("../container_spec.json").to_string();
|
let parent_snapshot = self.get_parent_snapshot(cid, ns).await?;
|
||||||
// let spec = Any {
|
let req = PrepareSnapshotRequest {
|
||||||
// type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(),
|
snapshotter: "overlayfs".to_string(),
|
||||||
// value: spec.into_bytes(),
|
key: cid.to_string(),
|
||||||
// };
|
parent: parent_snapshot,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let resp = self
|
||||||
|
.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.snapshots()
|
||||||
|
.prepare(with_namespace!(req, ns))
|
||||||
|
.await?
|
||||||
|
.into_inner()
|
||||||
|
.mounts;
|
||||||
|
|
||||||
|
Ok(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_container(&self, image_name: &str, cid: &str, ns: &str) -> Result<(), Err> {
|
||||||
|
let namespace = match ns {
|
||||||
|
"" => spec::DEFAULT_NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
|
||||||
|
let _mount = self.prepare_snapshot(cid, ns).await?;
|
||||||
|
|
||||||
|
let spec_path = generate_spec(&cid, ns).unwrap();
|
||||||
|
let spec = fs::read_to_string(spec_path).unwrap();
|
||||||
|
|
||||||
|
let spec = Any {
|
||||||
|
type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(),
|
||||||
|
value: spec.into_bytes(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut containers_client = self.client.lock().unwrap().containers();
|
let mut containers_client = self.client.lock().unwrap().containers();
|
||||||
let container = Container {
|
let container = Container {
|
||||||
id: cid.to_string(),
|
id: cid.to_string(),
|
||||||
image,
|
image: image_name.to_string(),
|
||||||
runtime: Some(Runtime {
|
runtime: Some(Runtime {
|
||||||
name: "io.containerd.runc.v2".to_string(),
|
name: "io.containerd.runc.v2".to_string(),
|
||||||
options: None,
|
options: None,
|
||||||
}),
|
}),
|
||||||
// spec: Some(spec),
|
spec: Some(spec),
|
||||||
|
snapshotter: "overlayfs".to_string(),
|
||||||
|
snapshot_key: cid.to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,38 +98,49 @@ impl Service {
|
|||||||
container: Some(container),
|
container: Some(container),
|
||||||
};
|
};
|
||||||
|
|
||||||
let req = with_namespace!(req, NAMESPACE);
|
let req = with_namespace!(req, namespace);
|
||||||
|
|
||||||
let _resp = containers_client
|
let _resp = containers_client
|
||||||
.create(req)
|
.create(req)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to create container");
|
.expect("Failed to create container");
|
||||||
|
|
||||||
println!("Container: {:?} created", cid);
|
// println!("Container: {:?} created", cid);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_container(&self, container_id: String) {
|
pub async fn remove_container(&self, cid: &str, ns: &str) -> Result<(), Err> {
|
||||||
|
let namespace = match ns {
|
||||||
|
"" => NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
let c = self.client.lock().unwrap();
|
let c = self.client.lock().unwrap();
|
||||||
let mut containers_client = c.containers();
|
let request = ListContainersRequest {
|
||||||
let request = Request::new(ListContainersRequest {
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
|
let mut cc = c.containers();
|
||||||
|
|
||||||
let responce = containers_client.list(request).await.unwrap().into_inner();
|
let responce = cc
|
||||||
|
.list(with_namespace!(request, namespace))
|
||||||
|
.await?
|
||||||
|
.into_inner();
|
||||||
let container = responce
|
let container = responce
|
||||||
.containers
|
.containers
|
||||||
.iter()
|
.iter()
|
||||||
.find(|container| container.id == container_id);
|
.find(|container| container.id == cid);
|
||||||
|
|
||||||
if let Some(container) = container {
|
if let Some(container) = container {
|
||||||
let mut tasks_client = c.tasks();
|
let mut tc = c.tasks();
|
||||||
|
|
||||||
let request = Request::new(ListTasksRequest {
|
let request = ListTasksRequest {
|
||||||
filter: format!("container=={}", container_id),
|
filter: format!("container=={}", cid),
|
||||||
// ..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
let responce = tasks_client.list(request).await.unwrap().into_inner();
|
let responce = tc
|
||||||
drop(tasks_client);
|
.list(with_namespace!(request, namespace))
|
||||||
|
.await?
|
||||||
|
.into_inner();
|
||||||
|
drop(tc);
|
||||||
if let Some(task) = responce
|
if let Some(task) = responce
|
||||||
.tasks
|
.tasks
|
||||||
.iter()
|
.iter()
|
||||||
@ -103,79 +154,104 @@ impl Service {
|
|||||||
// TASK_EXITED (4) — 任务已退出
|
// TASK_EXITED (4) — 任务已退出
|
||||||
// TASK_PAUSED (5) — 任务已暂停
|
// TASK_PAUSED (5) — 任务已暂停
|
||||||
// TASK_FAILED (6) — 任务失败
|
// TASK_FAILED (6) — 任务失败
|
||||||
self.delete_task(&task.container_id).await;
|
self.delete_task(&task.container_id, ns).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let delete_request = DeleteContainerRequest {
|
let delete_request = DeleteContainerRequest {
|
||||||
id: container.id.clone(),
|
id: container.id.clone(),
|
||||||
// ..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let delete_request = with_namespace!(delete_request, NAMESPACE);
|
|
||||||
|
|
||||||
let _ = containers_client
|
let _ = cc
|
||||||
.delete(delete_request)
|
.delete(with_namespace!(delete_request, namespace))
|
||||||
.await
|
.await
|
||||||
.expect("Failed to delete container");
|
.expect("Failed to delete container");
|
||||||
|
|
||||||
println!("Container: {:?} deleted", containers_client);
|
// println!("Container: {:?} deleted", cc);
|
||||||
} else {
|
} else {
|
||||||
todo!("Container not found");
|
todo!("Container not found");
|
||||||
}
|
}
|
||||||
drop(containers_client);
|
drop(cc);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_and_start_task(&self, container_id: String) {
|
pub async fn create_and_start_task(&self, cid: &str, ns: &str) -> Result<(), Err> {
|
||||||
let tmp = std::env::temp_dir().join("containerd-client-test");
|
// let tmp = std::env::temp_dir().join("containerd-client-test");
|
||||||
println!("Temp dir: {:?}", tmp);
|
// println!("Temp dir: {:?}", tmp);
|
||||||
fs::create_dir_all(&tmp).expect("Failed to create temp directory");
|
// fs::create_dir_all(&tmp).expect("Failed to create temp directory");
|
||||||
let stdin = tmp.join("stdin");
|
// let stdin = tmp.join("stdin");
|
||||||
let stdout = tmp.join("stdout");
|
// let stdout = tmp.join("stdout");
|
||||||
let stderr = tmp.join("stderr");
|
// let stderr = tmp.join("stderr");
|
||||||
File::create(&stdin).expect("Failed to create stdin");
|
// File::create(&stdin).expect("Failed to create stdin");
|
||||||
File::create(&stdout).expect("Failed to create stdout");
|
// File::create(&stdout).expect("Failed to create stdout");
|
||||||
File::create(&stderr).expect("Failed to create stderr");
|
// File::create(&stderr).expect("Failed to create stderr");
|
||||||
|
|
||||||
let mut tasks_client = self.client.lock().unwrap().tasks();
|
let namespace = match ns {
|
||||||
|
"" => spec::DEFAULT_NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
self.create_task(cid, namespace).await?;
|
||||||
|
self.start_task(cid, namespace).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_task(&self, cid: &str, ns: &str) -> Result<(), Err> {
|
||||||
|
let c = self.client.lock().unwrap();
|
||||||
|
let mut sc = c.snapshots();
|
||||||
|
let req = MountsRequest {
|
||||||
|
snapshotter: "overlayfs".to_string(),
|
||||||
|
key: cid.to_string(),
|
||||||
|
};
|
||||||
|
let mounts = sc
|
||||||
|
.mounts(with_namespace!(req, ns))
|
||||||
|
.await?
|
||||||
|
.into_inner()
|
||||||
|
.mounts;
|
||||||
|
drop(sc);
|
||||||
|
let mut tc = c.tasks();
|
||||||
let req = CreateTaskRequest {
|
let req = CreateTaskRequest {
|
||||||
container_id: container_id.clone(),
|
container_id: cid.to_string(),
|
||||||
stdin: stdin.to_str().unwrap().to_string(),
|
rootfs: mounts,
|
||||||
stdout: stdout.to_str().unwrap().to_string(),
|
|
||||||
stderr: stderr.to_str().unwrap().to_string(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let req = with_namespace!(req, NAMESPACE);
|
let _resp = tc.create(with_namespace!(req, ns)).await?;
|
||||||
|
|
||||||
let _resp = tasks_client
|
Ok(())
|
||||||
.create(req)
|
|
||||||
.await
|
|
||||||
.expect("Failed to create task");
|
|
||||||
|
|
||||||
println!("Task: {:?} created", container_id);
|
|
||||||
|
|
||||||
let req = StartRequest {
|
|
||||||
container_id: container_id.to_string(),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let req = with_namespace!(req, NAMESPACE);
|
|
||||||
|
|
||||||
let _resp = tasks_client.start(req).await.expect("Failed to start task");
|
|
||||||
|
|
||||||
println!("Task: {:?} started", container_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn kill_task(&self, container_id: String) {
|
async fn start_task(&self, cid: &str, ns: &str) -> Result<(), Err> {
|
||||||
let mut tasks_client = self.client.lock().unwrap().tasks();
|
let req = StartRequest {
|
||||||
let kill_request = Request::new(KillRequest {
|
container_id: cid.to_string(),
|
||||||
container_id: container_id.to_string(),
|
..Default::default()
|
||||||
|
};
|
||||||
|
let _resp = self
|
||||||
|
.client
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.tasks()
|
||||||
|
.start(with_namespace!(req, ns))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn kill_task(&self, cid: String, ns: &str) -> Result<(), Err> {
|
||||||
|
let namespace = match ns {
|
||||||
|
"" => NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
let mut c = self.client.lock().unwrap().tasks();
|
||||||
|
let kill_request = KillRequest {
|
||||||
|
container_id: cid.to_string(),
|
||||||
signal: 15,
|
signal: 15,
|
||||||
all: true,
|
all: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
tasks_client
|
c.kill(with_namespace!(kill_request, namespace))
|
||||||
.kill(kill_request)
|
|
||||||
.await
|
.await
|
||||||
.expect("Failed to kill task");
|
.expect("Failed to kill task");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn pause_task() {
|
pub async fn pause_task() {
|
||||||
todo!()
|
todo!()
|
||||||
@ -183,62 +259,74 @@ impl Service {
|
|||||||
pub async fn resume_task() {
|
pub async fn resume_task() {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
pub async fn delete_task(&self, container_id: &str) {
|
pub async fn delete_task(&self, cid: &str, ns: &str) {
|
||||||
|
let namespace = match ns {
|
||||||
|
"" => NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
let mut c = self.client.lock().unwrap().tasks();
|
||||||
let time_out = Duration::from_secs(30);
|
let time_out = Duration::from_secs(30);
|
||||||
let mut tc = self.client.lock().unwrap().tasks();
|
|
||||||
let wait_result = timeout(time_out, async {
|
let wait_result = timeout(time_out, async {
|
||||||
let wait_request = Request::new(WaitRequest {
|
let wait_request = WaitRequest {
|
||||||
container_id: container_id.to_string(),
|
container_id: cid.to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
|
|
||||||
let _ = tc.wait(wait_request).await?;
|
let _ = c.wait(with_namespace!(wait_request, namespace)).await?;
|
||||||
Ok::<(), Err>(())
|
Ok::<(), Err>(())
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let kill_request = Request::new(KillRequest {
|
let kill_request = KillRequest {
|
||||||
container_id: container_id.to_string(),
|
container_id: cid.to_string(),
|
||||||
signal: 15,
|
signal: 15,
|
||||||
all: true,
|
all: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
tc.kill(kill_request).await.expect("Failed to kill task");
|
c.kill(with_namespace!(kill_request, namespace))
|
||||||
|
.await
|
||||||
|
.expect("Failed to kill task");
|
||||||
|
|
||||||
match wait_result {
|
match wait_result {
|
||||||
Ok(Ok(_)) => {
|
Ok(Ok(_)) => {
|
||||||
let req = DeleteTaskRequest {
|
let req = DeleteTaskRequest {
|
||||||
container_id: container_id.to_string(),
|
container_id: cid.to_string(),
|
||||||
};
|
};
|
||||||
let req = with_namespace!(req, NAMESPACE);
|
|
||||||
|
|
||||||
let _resp = tc.delete(req).await.expect("Failed to delete task");
|
let _resp = c
|
||||||
println!("Task: {:?} deleted", container_id);
|
.delete(with_namespace!(req, namespace))
|
||||||
|
.await
|
||||||
|
.expect("Failed to delete task");
|
||||||
|
println!("Task: {:?} deleted", cid);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let kill_request = Request::new(KillRequest {
|
let kill_request = KillRequest {
|
||||||
container_id: container_id.to_string(),
|
container_id: cid.to_string(),
|
||||||
signal: 9,
|
signal: 9,
|
||||||
all: true,
|
all: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
};
|
||||||
tc.kill(kill_request)
|
c.kill(with_namespace!(kill_request, namespace))
|
||||||
.await
|
.await
|
||||||
.expect("Failed to FORCE kill task");
|
.expect("Failed to FORCE kill task");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_container_list(&self) -> Result<Vec<String>, tonic::Status> {
|
pub async fn get_container_list(&self, ns: &str) -> Result<Vec<String>, tonic::Status> {
|
||||||
let mut cc = self.client.lock().unwrap().containers();
|
let namespace = match ns {
|
||||||
|
"" => NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
let mut c = self.client.lock().unwrap().containers();
|
||||||
|
|
||||||
let request = ListContainersRequest {
|
let request = ListContainersRequest {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let request = with_namespace!(request, NAMESPACE);
|
let request = with_namespace!(request, namespace);
|
||||||
|
|
||||||
let response = cc.list(request).await?;
|
let response = c.list(request).await?;
|
||||||
|
|
||||||
Ok(response
|
Ok(response
|
||||||
.into_inner()
|
.into_inner()
|
||||||
@ -248,7 +336,9 @@ impl Service {
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_task_list() {}
|
pub async fn get_task_list() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prepare_image(&self) {
|
pub fn prepare_image(&self) {
|
||||||
todo!()
|
todo!()
|
||||||
@ -260,6 +350,174 @@ impl Service {
|
|||||||
pub fn get_resolver(&self) {
|
pub fn get_resolver(&self) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_index(&self, data: &Vec<u8>, ns: &str) -> Option<ImageConfiguration> {
|
||||||
|
let image_index: ImageIndex = ::serde_json::from_slice(&data).unwrap();
|
||||||
|
let img_manifest_dscr = image_index
|
||||||
|
.manifests()
|
||||||
|
.iter()
|
||||||
|
.find(|manifest_entry| match manifest_entry.platform() {
|
||||||
|
Some(p) => {
|
||||||
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||||
|
{
|
||||||
|
matches!(p.architecture(), &Arch::Amd64) && matches!(p.os(), &Os::Linux)
|
||||||
|
}
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
matches!(p.architecture(), &Arch::ARM64) && matches!(p.os(), Os::Linux)
|
||||||
|
//&& matches!(p.variant().as_ref().map(|s| s.as_str()), Some("v8"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let req = ReadContentRequest {
|
||||||
|
digest: img_manifest_dscr.digest().to_owned(),
|
||||||
|
offset: 0,
|
||||||
|
size: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut c = self.client.lock().unwrap().content();
|
||||||
|
let resp = c
|
||||||
|
.read(with_namespace!(req, ns))
|
||||||
|
.await
|
||||||
|
.expect("Failed to read content")
|
||||||
|
.into_inner()
|
||||||
|
.message()
|
||||||
|
.await
|
||||||
|
.expect("Failed to read content message")
|
||||||
|
.unwrap()
|
||||||
|
.data;
|
||||||
|
|
||||||
|
self.handle_manifest(&resp, ns).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_manifest(&self, data: &Vec<u8>, ns: &str) -> Option<ImageConfiguration> {
|
||||||
|
let img_manifest: ImageManifest = ::serde_json::from_slice(&data).unwrap();
|
||||||
|
let img_manifest_dscr = img_manifest.config();
|
||||||
|
|
||||||
|
let req = ReadContentRequest {
|
||||||
|
digest: img_manifest_dscr.digest().to_owned(),
|
||||||
|
offset: 0,
|
||||||
|
size: 0,
|
||||||
|
};
|
||||||
|
let mut c = self.client.lock().unwrap().content();
|
||||||
|
|
||||||
|
let resp = c
|
||||||
|
.read(with_namespace!(req, ns))
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.into_inner()
|
||||||
|
.message()
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.data;
|
||||||
|
|
||||||
|
::serde_json::from_slice(&resp).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_img_config(&self, name: &str, ns: &str) -> Option<ImageConfiguration> {
|
||||||
|
let mut c = self.client.lock().unwrap().images();
|
||||||
|
|
||||||
|
let req = GetImageRequest {
|
||||||
|
name: name.to_string(),
|
||||||
|
};
|
||||||
|
let resp = c
|
||||||
|
.get(with_namespace!(req, ns))
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to get the config of {} in namespace {}: {}",
|
||||||
|
name, ns, e
|
||||||
|
);
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok()?
|
||||||
|
.into_inner();
|
||||||
|
|
||||||
|
let img_dscr = resp.image?.target?;
|
||||||
|
let media_type = MediaType::from(img_dscr.media_type.as_str());
|
||||||
|
|
||||||
|
let req = ReadContentRequest {
|
||||||
|
digest: img_dscr.digest,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut c = self.client.lock().unwrap().content();
|
||||||
|
|
||||||
|
let resp = c
|
||||||
|
.read(with_namespace!(req, ns))
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to read content for {} in namespace {}: {}",
|
||||||
|
name, ns, e
|
||||||
|
);
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok()?
|
||||||
|
.into_inner()
|
||||||
|
.message()
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to read message for {} in namespace {}: {}",
|
||||||
|
name, ns, e
|
||||||
|
);
|
||||||
|
e
|
||||||
|
})
|
||||||
|
.ok()?
|
||||||
|
.ok_or_else(|| {
|
||||||
|
eprintln!("No data found for {} in namespace {}", name, ns);
|
||||||
|
std::io::Error::new(std::io::ErrorKind::NotFound, "No data found")
|
||||||
|
})
|
||||||
|
.ok()?
|
||||||
|
.data;
|
||||||
|
|
||||||
|
let img_config = match media_type {
|
||||||
|
MediaType::ImageIndex => self.handle_index(&resp, ns).await.unwrap(),
|
||||||
|
MediaType::ImageManifest => self.handle_manifest(&resp, ns).await.unwrap(),
|
||||||
|
MediaType::Other(media_type) => match media_type.as_str() {
|
||||||
|
"application/vnd.docker.distribution.manifest.list.v2+json" => {
|
||||||
|
self.handle_index(&resp, ns).await.unwrap()
|
||||||
|
}
|
||||||
|
"application/vnd.docker.distribution.manifest.v2+json" => {
|
||||||
|
self.handle_manifest(&resp, ns).await.unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("Unexpected media type '{}'", media_type);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
eprintln!("Unexpected media type '{}'", media_type);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(img_config)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_parent_snapshot(&self, name: &str, ns: &str) -> Result<String, Err> {
|
||||||
|
let img_config = self.get_img_config(name, ns).await.unwrap();
|
||||||
|
|
||||||
|
let mut iter = img_config.rootfs().diff_ids().iter();
|
||||||
|
let mut ret = iter
|
||||||
|
.next()
|
||||||
|
.map_or_else(String::new, |layer_digest| layer_digest.clone());
|
||||||
|
|
||||||
|
while let Some(layer_digest) = iter.next() {
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(ret.as_bytes());
|
||||||
|
ret.push_str(&format!(",{}", layer_digest));
|
||||||
|
hasher.update(" ");
|
||||||
|
hasher.update(layer_digest);
|
||||||
|
let digest = ::hex::encode(hasher.finalize());
|
||||||
|
ret = format!("sha256:{digest}");
|
||||||
|
}
|
||||||
|
Ok(ret)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//容器是容器,要先启动,然后才能运行任务
|
//容器是容器,要先启动,然后才能运行任务
|
||||||
//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。
|
//要想删除一个正在运行的Task,必须先kill掉这个task,然后才能删除。
|
||||||
|
318
crates/service/src/spec.rs
Normal file
318
crates/service/src/spec.rs
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
// 定义版本的常量
|
||||||
|
const VERSION_MAJOR: u32 = 1;
|
||||||
|
const VERSION_MINOR: u32 = 1;
|
||||||
|
const VERSION_PATCH: u32 = 0;
|
||||||
|
const VERSION_DEV: &str = ""; // 对应开发分支
|
||||||
|
|
||||||
|
const RWM: &str = "rwm";
|
||||||
|
const DEFAULT_ROOTFS_PATH: &str = "rootfs";
|
||||||
|
pub const DEFAULT_NAMESPACE: &str = "default";
|
||||||
|
const PATH_TO_SPEC_PREFIX: &str = "/tmp/containerd-spec";
|
||||||
|
|
||||||
|
// const DEFAULT_UNIX_ENV: &str = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
||||||
|
|
||||||
|
const PID_NAMESPACE: &str = "pid";
|
||||||
|
const NETWORK_NAMESPACE: &str = "network";
|
||||||
|
const MOUNT_NAMESPACE: &str = "mount";
|
||||||
|
const IPC_NAMESPACE: &str = "ipc";
|
||||||
|
const UTS_NAMESPACE: &str = "uts";
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Spec {
|
||||||
|
#[serde(rename = "ociVersion")]
|
||||||
|
pub oci_version: String,
|
||||||
|
pub root: Root,
|
||||||
|
pub process: Process,
|
||||||
|
pub linux: Linux,
|
||||||
|
pub mounts: Vec<Mount>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Root {
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Process {
|
||||||
|
pub cwd: String,
|
||||||
|
#[serde(rename = "noNewPrivileges")]
|
||||||
|
pub no_new_privileges: bool,
|
||||||
|
pub user: User,
|
||||||
|
pub capabilities: LinuxCapabilities,
|
||||||
|
pub rlimits: Vec<POSIXRlimit>,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
pub env: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct User {
|
||||||
|
pub uid: u32,
|
||||||
|
pub gid: u32,
|
||||||
|
#[serde(rename = "additionalGids")]
|
||||||
|
pub additional_gids: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Mount {
|
||||||
|
pub destination: String,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub source: String,
|
||||||
|
pub options: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LinuxCapabilities {
|
||||||
|
pub bounding: Vec<String>,
|
||||||
|
pub permitted: Vec<String>,
|
||||||
|
pub effective: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct POSIXRlimit {
|
||||||
|
pub hard: u64,
|
||||||
|
pub soft: u64,
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Linux {
|
||||||
|
pub masked_paths: Vec<String>,
|
||||||
|
pub readonly_paths: Vec<String>,
|
||||||
|
pub cgroups_path: String,
|
||||||
|
pub resources: LinuxResources,
|
||||||
|
pub namespaces: Vec<LinuxNamespace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LinuxResources {
|
||||||
|
pub devices: Vec<LinuxDeviceCgroup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LinuxDeviceCgroup {
|
||||||
|
pub allow: bool,
|
||||||
|
pub access: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct LinuxNamespace {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_unix_caps() -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
String::from("CAP_CHOWN"),
|
||||||
|
String::from("CAP_DAC_OVERRIDE"),
|
||||||
|
String::from("CAP_FSETID"),
|
||||||
|
String::from("CAP_FOWNER"),
|
||||||
|
String::from("CAP_MKNOD"),
|
||||||
|
String::from("CAP_NET_RAW"),
|
||||||
|
String::from("CAP_SETGID"),
|
||||||
|
String::from("CAP_SETUID"),
|
||||||
|
String::from("CAP_SETFCAP"),
|
||||||
|
String::from("CAP_SETPCAP"),
|
||||||
|
String::from("CAP_NET_BIND_SERVICE"),
|
||||||
|
String::from("CAP_SYS_CHROOT"),
|
||||||
|
String::from("CAP_KILL"),
|
||||||
|
String::from("CAP_AUDIT_WRITE"),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_masked_parhs() -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
String::from("/proc/acpi"),
|
||||||
|
String::from("/proc/asound"),
|
||||||
|
String::from("/proc/kcore"),
|
||||||
|
String::from("/proc/keys"),
|
||||||
|
String::from("/proc/latency_stats"),
|
||||||
|
String::from("/proc/timer_list"),
|
||||||
|
String::from("/proc/timer_stats"),
|
||||||
|
String::from("/proc/sched_debug"),
|
||||||
|
String::from("/proc/scsi"),
|
||||||
|
String::from("/sys/firmware"),
|
||||||
|
String::from("/sys/devices/virtual/powercap"),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_readonly_paths() -> Vec<String> {
|
||||||
|
vec![
|
||||||
|
String::from("/proc/bus"),
|
||||||
|
String::from("/proc/fs"),
|
||||||
|
String::from("/proc/irq"),
|
||||||
|
String::from("/proc/sys"),
|
||||||
|
String::from("/proc/sysrq-trigger"),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_unix_namespaces() -> Vec<LinuxNamespace> {
|
||||||
|
vec![
|
||||||
|
LinuxNamespace {
|
||||||
|
type_: String::from(PID_NAMESPACE),
|
||||||
|
},
|
||||||
|
LinuxNamespace {
|
||||||
|
type_: String::from(IPC_NAMESPACE),
|
||||||
|
},
|
||||||
|
LinuxNamespace {
|
||||||
|
type_: String::from(UTS_NAMESPACE),
|
||||||
|
},
|
||||||
|
LinuxNamespace {
|
||||||
|
type_: String::from(MOUNT_NAMESPACE),
|
||||||
|
},
|
||||||
|
LinuxNamespace {
|
||||||
|
type_: String::from(NETWORK_NAMESPACE),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_mounts() -> Vec<Mount> {
|
||||||
|
vec![
|
||||||
|
Mount {
|
||||||
|
destination: "/proc".to_string(),
|
||||||
|
type_: "proc".to_string(),
|
||||||
|
source: "proc".to_string(),
|
||||||
|
options: vec![],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/dev".to_string(),
|
||||||
|
type_: "tmpfs".to_string(),
|
||||||
|
source: "tmpfs".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"strictatime".to_string(),
|
||||||
|
"mode=755".to_string(),
|
||||||
|
"size=65536k".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/dev/pts".to_string(),
|
||||||
|
type_: "devpts".to_string(),
|
||||||
|
source: "devpts".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"noexec".to_string(),
|
||||||
|
"newinstance".to_string(),
|
||||||
|
"ptmxmode=0666".to_string(),
|
||||||
|
"mode=0620".to_string(),
|
||||||
|
"gid=5".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/dev/shm".to_string(),
|
||||||
|
type_: "tmpfs".to_string(),
|
||||||
|
source: "shm".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"noexec".to_string(),
|
||||||
|
"nodev".to_string(),
|
||||||
|
"mode=1777".to_string(),
|
||||||
|
"size=65536k".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/dev/mqueue".to_string(),
|
||||||
|
type_: "mqueue".to_string(),
|
||||||
|
source: "mqueue".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"noexec".to_string(),
|
||||||
|
"nodev".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/sys".to_string(),
|
||||||
|
type_: "sysfs".to_string(),
|
||||||
|
source: "sysfs".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"noexec".to_string(),
|
||||||
|
"nodev".to_string(),
|
||||||
|
"ro".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
Mount {
|
||||||
|
destination: "/sys/fs/cgroup".to_string(),
|
||||||
|
type_: "cgroup".to_string(),
|
||||||
|
source: "cgroup".to_string(),
|
||||||
|
options: vec![
|
||||||
|
"nosuid".to_string(),
|
||||||
|
"noexec".to_string(),
|
||||||
|
"nodev".to_string(),
|
||||||
|
"relatime".to_string(),
|
||||||
|
"ro".to_string(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_version() -> String {
|
||||||
|
format!(
|
||||||
|
"{}.{}.{}{}",
|
||||||
|
VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_DEV
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_default_unix_spec(id: &str, ns: &str) -> Spec {
|
||||||
|
Spec {
|
||||||
|
oci_version: get_version(),
|
||||||
|
root: Root {
|
||||||
|
path: DEFAULT_ROOTFS_PATH.to_string(),
|
||||||
|
},
|
||||||
|
process: Process {
|
||||||
|
cwd: String::from("/"),
|
||||||
|
no_new_privileges: true,
|
||||||
|
user: User {
|
||||||
|
uid: 0,
|
||||||
|
gid: 0,
|
||||||
|
additional_gids: vec![],
|
||||||
|
},
|
||||||
|
capabilities: LinuxCapabilities {
|
||||||
|
bounding: default_unix_caps(),
|
||||||
|
permitted: default_unix_caps(),
|
||||||
|
effective: default_unix_caps(),
|
||||||
|
},
|
||||||
|
rlimits: vec![POSIXRlimit {
|
||||||
|
type_: String::from("RLIMIT_NOFILE"),
|
||||||
|
hard: 1024,
|
||||||
|
soft: 1024,
|
||||||
|
}],
|
||||||
|
args: vec![],
|
||||||
|
env: vec![],
|
||||||
|
},
|
||||||
|
linux: Linux {
|
||||||
|
masked_paths: default_masked_parhs(),
|
||||||
|
readonly_paths: default_readonly_paths(),
|
||||||
|
cgroups_path: format!("{}/{}", ns, id),
|
||||||
|
resources: LinuxResources {
|
||||||
|
devices: vec![LinuxDeviceCgroup {
|
||||||
|
allow: false,
|
||||||
|
access: RWM.to_string(),
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
namespaces: default_unix_namespaces(),
|
||||||
|
},
|
||||||
|
mounts: default_mounts(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save_spec_to_file(spec: &Spec, path: &str) -> Result<(), std::io::Error> {
|
||||||
|
let file = File::create(path)?;
|
||||||
|
serde_json::to_writer(file, spec)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_spec(id: &str, ns: &str) -> Result<String, std::io::Error> {
|
||||||
|
let namespace = match ns {
|
||||||
|
"" => DEFAULT_NAMESPACE,
|
||||||
|
_ => ns,
|
||||||
|
};
|
||||||
|
let spec = populate_default_unix_spec(id, ns);
|
||||||
|
let path = format!("{}/{}/{}.json", PATH_TO_SPEC_PREFIX, namespace, id);
|
||||||
|
save_spec_to_file(&spec, &path)?;
|
||||||
|
Ok(path)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user