Skip to content

Commit

Permalink
Merge pull request #33 from Burning1020/support-new-api
Browse files Browse the repository at this point in the history
sandbox: support the new sandbox controller api
  • Loading branch information
abel-von authored Jul 31, 2024
2 parents b9ad8e1 + 8febaf6 commit 3c942d7
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 165 deletions.
1 change: 1 addition & 0 deletions crates/sandbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ serde_derive = "1.0.130"
serde = "1.0.130"
time = "0.3.5"
pin-project-lite = "0.2.7"
base64 = "0.22.1"

[build-dependencies]
tonic-build = "0.7.2"
13 changes: 13 additions & 0 deletions crates/sandbox/src/base64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use serde::{Serialize, Deserialize};
use serde::{Deserializer, Serializer};

pub fn serialize<S: Serializer>(v: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
let base64 = base64::encode(v);
String::serialize(&base64, s)
}

pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
let base64 = String::deserialize(d)?;
base64::decode(base64.as_bytes())
.map_err(|e| serde::de::Error::custom(e))
}
116 changes: 85 additions & 31 deletions crates/sandbox/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use std::collections::HashMap;
use std::time::SystemTime;

use log::warn;
use prost::Message;
use serde::Deserialize;
use serde::Serialize;
use prost::Message;
use tonic::Status;

use crate::PodSandboxConfig;
use crate::spec::{JsonSpec, Mount, Process};
use crate::PodSandboxConfig;

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SandboxData {
Expand All @@ -25,12 +26,15 @@ pub struct SandboxData {

impl SandboxData {
pub fn new(req: &crate::api::sandbox::v1::ControllerCreateRequest) -> Self {
let config = req.options.as_ref().and_then(|x| {
let config: Option<PodSandboxConfig> = req.options.as_ref().and_then(|x| {
match PodSandboxConfig::decode(&*x.value) {
Ok(c) => { Some(c) }
Ok(c) => Some(c),
Err(e) => {
warn!("failed to parse container spec {} of {} from request, {}",
String::from_utf8_lossy(x.value.as_slice()),req.sandbox_id, e
warn!(
"failed to parse container spec {} of {} from request, {}",
String::from_utf8_lossy(x.value.as_slice()),
req.sandbox_id,
e
);
None
}
Expand All @@ -46,6 +50,14 @@ impl SandboxData {
// }
// }
});
let extensions = if let Some(sb) = &req.sandbox {
sb.extensions
.iter()
.map(|(k, v)| (k.clone(), Any::from(v)))
.collect()
} else {
Default::default()
};
Self {
id: req.sandbox_id.to_string(),
spec: None,
Expand All @@ -56,8 +68,18 @@ impl SandboxData {
netns: req.netns_path.to_string(),
started_at: None,
exited_at: None,
extensions: Default::default(),
extensions: extensions,
}
}

pub fn task_resources(&self) -> Result<TaskResources, Status> {
let mut tasks = TaskResources {tasks: vec![]};
if let Some(a) = self.extensions.get("tasks") {
tasks = serde_json::from_slice(a.value.as_slice()).map_err(|e| {
Status::invalid_argument(format!("failed to unmarshal old tasks {}", e))
})?;
}
Ok(tasks)
}
}

Expand Down Expand Up @@ -98,28 +120,16 @@ pub struct ContainerData {
}

impl ContainerData {
pub fn new(req: &crate::api::sandbox::v1::PrepareRequest) -> Self {
let spec = req.spec.as_ref().and_then(|x| {
match serde_json::from_slice::<JsonSpec>(x.value.as_slice()) {
Ok(s) => Some(s),
Err(e) => {
warn!(
"failed to parse container spec of {} from request, {}",
req.container_id, e
);
None
}
}
});
pub fn new(req: &crate::data::TaskResource) -> Self {
Self {
id: req.container_id.to_string(),
spec,
rootfs: req.rootfs.iter().map(Mount::from).collect(),
id: req.task_id.to_string(),
spec: req.spec.clone(),
rootfs: req.rootfs.clone(),
io: Some(Io {
stdin: req.stdin.to_string(),
stdout: req.stdout.to_string(),
stderr: req.stderr.to_string(),
terminal: req.terminal,
terminal: false,
}),
processes: vec![],
bundle: "".to_string(),
Expand All @@ -145,21 +155,55 @@ pub struct ProcessData {
pub extra: HashMap<String, Any>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct TaskResources {
#[serde(default)]
pub tasks: Vec<TaskResource>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct TaskResource {
#[serde(default)]
pub task_id: String,
#[serde(default)]
pub spec: Option<JsonSpec>,
#[serde(default)]
pub rootfs: Vec<Mount>,
#[serde(default)]
pub stdin: String,
#[serde(default)]
pub stdout: String,
#[serde(default)]
pub stderr: String,
#[serde(default)]
pub processes: Vec<ProcessResource>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ProcessResource {
#[serde(default)]
pub exec_id: String,
#[serde(default)]
pub spec: Option<Process>,
#[serde(default)]
pub stdin: String,
#[serde(default)]
pub stdout: String,
#[serde(default)]
pub stderr: String,
}

impl ProcessData {
pub fn new(req: &crate::api::sandbox::v1::PrepareRequest) -> Self {
let ps = req
.spec
.as_ref()
.and_then(|x| serde_json::from_slice::<Process>(x.value.as_slice()).ok());
pub fn new(req: &crate::data::ProcessResource) -> Self {
Self {
id: req.exec_id.to_string(),
io: Some(Io {
stdin: req.stdin.to_string(),
stdout: req.stdout.to_string(),
stderr: req.stderr.to_string(),
terminal: req.terminal,
terminal: false,
}),
process: ps,
process: req.spec.clone(),
extra: Default::default(),
}
}
Expand All @@ -168,6 +212,7 @@ impl ProcessData {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Any {
pub type_url: String,
#[serde(with="crate::base64")]
pub value: Vec<u8>,
}

Expand All @@ -180,6 +225,15 @@ impl From<prost_types::Any> for Any {
}
}

impl From<&prost_types::Any> for Any {
fn from(proto: &prost_types::Any) -> Self {
Self {
type_url: proto.type_url.clone(),
value: proto.value.clone(),
}
}
}

impl From<Any> for prost_types::Any {
fn from(any: Any) -> Self {
Self {
Expand Down
2 changes: 2 additions & 0 deletions crates/sandbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub mod rpc;
pub mod signal;
pub mod spec;
pub mod utils;
pub mod base64;

/// Generated GRPC apis.
pub mod api {
Expand Down Expand Up @@ -103,6 +104,7 @@ pub trait Sandboxer {
type Sandbox: Sandbox + Send + Sync;
async fn create(&self, id: &str, s: SandboxOption) -> Result<()>;
async fn start(&self, id: &str) -> Result<()>;
async fn update(&self, id: &str, s: SandboxData) -> Result<()>;
async fn sandbox(&self, id: &str) -> Result<Arc<Mutex<Self::Sandbox>>>;
async fn stop(&self, id: &str, force: bool) -> Result<()>;
async fn delete(&self, id: &str) -> Result<()>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

syntax = "proto3";

package containerd.types;

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/containerd/containerd/v2/api/types;types";

message Metric {
google.protobuf.Timestamp timestamp = 1;
string id = 2;
google.protobuf.Any data = 3;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ package containerd.types;
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option go_package = "github.com/containerd/containerd/api/types;types";
import "github.com/containerd/containerd/api/types/mount.proto";

option go_package = "github.com/containerd/containerd/v2/api/types;types";

// Sandbox represents a sandbox metadata object that keeps all info required by controller to
// work with a particular instance.
Expand All @@ -40,14 +42,21 @@ message Sandbox {
// Spec is sandbox configuration (kin of OCI runtime spec), spec's data will be written to a config.json file in the
// bundle directory (similary to OCI spec).
google.protobuf.Any spec = 3;
// Sandboxer is the name of the sandbox controller who manages the sandbox.
string sandboxer = 4;
// Labels provides an area to include arbitrary data on containers.
map<string, string> labels = 5;
map<string, string> labels = 4;
// CreatedAt is the time the container was first created.
google.protobuf.Timestamp created_at = 6;
google.protobuf.Timestamp created_at = 5;
// UpdatedAt is the last time the container was mutated.
google.protobuf.Timestamp updated_at = 7;
google.protobuf.Timestamp updated_at = 6;
// Extensions allow clients to provide optional blobs that can be handled by runtime.
map<string, google.protobuf.Any> extensions = 8;
map<string, google.protobuf.Any> extensions = 7;
// Sandboxer is the name of the sandbox controller who manages the sandbox.
string sandboxer = 10;

}

enum ResourceOp {
ADD = 0;
REMOVE = 1;
UPDATE = 2;
}
Loading

0 comments on commit 3c942d7

Please sign in to comment.