containerd-client: add example to create container and task
Add an example to show how to create/delete containers and tasks. Signed-off-by: bin liu <bin@hyper.sh>
This commit is contained in:
parent
2010a32a47
commit
cfca48d75c
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
use containerd_client as client;
|
||||
|
||||
use client::services::v1::container::Runtime;
|
||||
use client::services::v1::containers_client::ContainersClient;
|
||||
use client::services::v1::Container;
|
||||
use client::services::v1::{CreateContainerRequest, DeleteContainerRequest};
|
||||
|
||||
use client::services::v1::tasks_client::TasksClient;
|
||||
use client::services::v1::{CreateTaskRequest, DeleteTaskRequest, StartRequest, WaitRequest};
|
||||
|
||||
use prost_types::Any;
|
||||
|
||||
use tonic::Request;
|
||||
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
|
||||
use client::with_namespace;
|
||||
|
||||
const CID: &str = "abc123";
|
||||
const NAMESPACE: &str = "default";
|
||||
|
||||
/// Make sure you run containerd before running this example.
|
||||
/// NOTE: to run this example, you must prepare a rootfs.
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() {
|
||||
let channel = client::connect("/run/containerd/containerd.sock")
|
||||
.await
|
||||
.expect("Connect Failed");
|
||||
|
||||
let mut client = ContainersClient::new(channel.clone());
|
||||
|
||||
let rootfs = "/tmp/busybox/bundle/rootfs";
|
||||
// the container will run with command `echo $output`
|
||||
let output = "hello rust client";
|
||||
|
||||
let spec = include_str!("container_spec.json");
|
||||
let spec = spec
|
||||
.to_string()
|
||||
.replace("$ROOTFS", rootfs)
|
||||
.replace("$OUTPUT", output);
|
||||
|
||||
let spec = Any {
|
||||
type_url: "types.containerd.io/opencontainers/runtime-spec/1/Spec".to_string(),
|
||||
value: spec.into_bytes(),
|
||||
};
|
||||
|
||||
let container = Container {
|
||||
id: CID.to_string(),
|
||||
image: "docker.io/library/alpine:latest".to_string(),
|
||||
runtime: Some(Runtime {
|
||||
name: "io.containerd.runc.v2".to_string(),
|
||||
options: None,
|
||||
}),
|
||||
spec: Some(spec),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let req = CreateContainerRequest {
|
||||
container: Some(container),
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client
|
||||
.create(req)
|
||||
.await
|
||||
.expect("Failed to create container");
|
||||
|
||||
println!("Container: {:?} created", CID);
|
||||
|
||||
// create temp dir for stdin/stdout/stderr
|
||||
let tmp = std::env::temp_dir().join("containerd-client-test");
|
||||
fs::create_dir_all(&tmp).expect("Failed to create temp directory");
|
||||
let stdin = tmp.join("stdin");
|
||||
let stdout = tmp.join("stdout");
|
||||
let stderr = tmp.join("stderr");
|
||||
File::create(&stdin).expect("Failed to create stdin");
|
||||
File::create(&stdout).expect("Failed to create stdout");
|
||||
File::create(&stderr).expect("Failed to create stderr");
|
||||
|
||||
// creat and start task
|
||||
let mut client = TasksClient::new(channel.clone());
|
||||
|
||||
let req = CreateTaskRequest {
|
||||
container_id: CID.to_string(),
|
||||
stdin: stdin.to_str().unwrap().to_string(),
|
||||
stdout: stdout.to_str().unwrap().to_string(),
|
||||
stderr: stderr.to_str().unwrap().to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client.create(req).await.expect("Failed to create task");
|
||||
|
||||
println!("Task: {:?} created", CID);
|
||||
|
||||
let req = StartRequest {
|
||||
container_id: CID.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client.start(req).await.expect("Failed to start task");
|
||||
|
||||
println!("Task: {:?} started", CID);
|
||||
|
||||
// wait task
|
||||
let req = WaitRequest {
|
||||
container_id: CID.to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client.wait(req).await.expect("Failed to wait task");
|
||||
|
||||
println!("Task: {:?} stopped", CID);
|
||||
|
||||
// delete task
|
||||
let req = DeleteTaskRequest {
|
||||
container_id: CID.to_string(),
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client.delete(req).await.expect("Failed to delete task");
|
||||
|
||||
println!("Task: {:?} deleted", CID);
|
||||
|
||||
// delete container
|
||||
let mut client = ContainersClient::new(channel);
|
||||
|
||||
let req = DeleteContainerRequest {
|
||||
id: CID.to_string(),
|
||||
};
|
||||
let req = with_namespace!(req, NAMESPACE);
|
||||
|
||||
let _resp = client
|
||||
.delete(req)
|
||||
.await
|
||||
.expect("Failed to delete container");
|
||||
|
||||
println!("Container: {:?} deleted", CID);
|
||||
|
||||
// test container output
|
||||
let actual_stdout = fs::read_to_string(stdout).expect("read stdout actual");
|
||||
assert_eq!(actual_stdout.strip_suffix("\n").unwrap(), output);
|
||||
|
||||
// clear stdin/stdout/stderr
|
||||
let _ = fs::remove_dir_all(tmp);
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
{
|
||||
"ociVersion": "1.0.0-rc2-dev",
|
||||
"platform": {
|
||||
"os": "linux",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"process": {
|
||||
"terminal": false,
|
||||
"consoleSize": {
|
||||
"height": 0,
|
||||
"width": 0
|
||||
},
|
||||
"user": {
|
||||
"uid": 0,
|
||||
"gid": 0
|
||||
},
|
||||
"args": [ "echo", "$OUTPUT" ],
|
||||
"env": [
|
||||
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
"TERM=xterm"
|
||||
],
|
||||
"cwd": "/",
|
||||
"rlimits": [{
|
||||
"type": "RLIMIT_NOFILE",
|
||||
"hard": 1024,
|
||||
"soft": 1024
|
||||
}],
|
||||
"noNewPrivileges": true
|
||||
},
|
||||
"root": {
|
||||
"path": "$ROOTFS",
|
||||
"readonly": false
|
||||
},
|
||||
"hostname": "test",
|
||||
"mounts": [{
|
||||
"destination": "/proc",
|
||||
"type": "proc",
|
||||
"source": "proc"
|
||||
},
|
||||
{
|
||||
"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": "/sys/fs/cgroup",
|
||||
"type": "cgroup",
|
||||
"source": "cgroup",
|
||||
"options": [
|
||||
"nosuid",
|
||||
"noexec",
|
||||
"nodev",
|
||||
"relatime",
|
||||
"ro"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hooks": {},
|
||||
"linux": {
|
||||
"devices": [],
|
||||
"cgroupsPath": "kata/vfiotest",
|
||||
"resources": {
|
||||
"devices": [
|
||||
{"allow":false,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":1,"minor":3,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":1,"minor":5,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":1,"minor":8,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":1,"minor":9,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":5,"minor":0,"access":"rwm"},
|
||||
{"allow":true,"type":"c","major":5,"minor":1,"access":"rwm"}
|
||||
]
|
||||
},
|
||||
"namespaces": [{
|
||||
"type": "pid"
|
||||
},
|
||||
{
|
||||
"type": "network"
|
||||
},
|
||||
{
|
||||
"type": "ipc"
|
||||
},
|
||||
{
|
||||
"type": "uts"
|
||||
},
|
||||
{
|
||||
"type": "mount"
|
||||
}
|
||||
],
|
||||
"maskedPaths": [
|
||||
"/proc/kcore",
|
||||
"/proc/latency_stats",
|
||||
"/proc/timer_list",
|
||||
"/proc/timer_stats",
|
||||
"/proc/sched_debug",
|
||||
"/sys/firmware"
|
||||
],
|
||||
"readonlyPaths": [
|
||||
"/proc/asound",
|
||||
"/proc/bus",
|
||||
"/proc/fs",
|
||||
"/proc/irq",
|
||||
"/proc/sys",
|
||||
"/proc/sysrq-trigger"
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue