From 6e4775ccca72ec12bba2f80ddee0ba226c6e6f13 Mon Sep 17 00:00:00 2001 From: jokemanfire Date: Tue, 21 Jan 2025 14:45:23 +0800 Subject: [PATCH] Add info for get runtimeinfo This interface is already in goshim. Use containerd-shim-runc-v2 --info. Signed-off-by: jokemanfire --- crates/runc-shim/Cargo.toml | 2 +- crates/runc-shim/src/main.rs | 33 +++++++++++- crates/shim-protos/build.rs | 1 + crates/shim-protos/src/types.rs | 3 ++ .../containerd/api/types/introspection.proto | 46 ++++++++++++++++ crates/shim/Cargo.toml | 1 + crates/shim/src/args.rs | 3 ++ crates/shim/src/asynchronous/mod.rs | 54 +++++++++++++++++-- 8 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 crates/shim-protos/vendor/github.com/containerd/containerd/api/types/introspection.proto diff --git a/crates/runc-shim/Cargo.toml b/crates/runc-shim/Cargo.toml index 90f9ad7c..04074abf 100644 --- a/crates/runc-shim/Cargo.toml +++ b/crates/runc-shim/Cargo.toml @@ -36,7 +36,7 @@ serde.workspace = true serde_json.workspace = true time.workspace = true uuid.workspace = true - +tempfile.workspace = true # Async dependencies async-trait.workspace = true tokio = { workspace = true, features = ["full"] } diff --git a/crates/runc-shim/src/main.rs b/crates/runc-shim/src/main.rs index d95d04ba..1a09b088 100644 --- a/crates/runc-shim/src/main.rs +++ b/crates/runc-shim/src/main.rs @@ -14,9 +14,14 @@ limitations under the License. */ -use std::env; +use std::{env, io::Write}; -use containerd_shim::{asynchronous::run, parse}; +use containerd_shim::{ + asynchronous::run, + parse, + protos::protobuf::{well_known_types::any::Any, Message}, + run_info, +}; mod cgroup_memory; mod common; @@ -47,6 +52,30 @@ fn parse_version() { std::process::exit(0); } + if flags.info { + let r = run_info(); + match r { + Ok(rinfo) => { + let mut info = Any::new(); + info.type_url = "io.containerd.runc.v2.Info".to_string(); + info.value = match rinfo.write_to_bytes() { + Ok(bytes) => bytes, + Err(e) => { + eprintln!("Failed to write runtime info to bytes: {}", e); + std::process::exit(1); + } + }; + std::io::stdout() + .write_all(info.write_to_bytes().unwrap().as_slice()) + .expect("Failed to write to stdout"); + } + Err(_) => { + eprintln!("Failed to get runtime info"); + std::process::exit(1); + } + } + std::process::exit(0); + } } #[tokio::main] diff --git a/crates/shim-protos/build.rs b/crates/shim-protos/build.rs index fdeb6840..d5e1c006 100644 --- a/crates/shim-protos/build.rs +++ b/crates/shim-protos/build.rs @@ -32,6 +32,7 @@ fn main() { "vendor/github.com/containerd/containerd/protobuf/plugin/fieldpath.proto", "vendor/github.com/containerd/containerd/api/types/mount.proto", "vendor/github.com/containerd/containerd/api/types/task/task.proto", + "vendor/github.com/containerd/containerd/api/types/introspection.proto", #[cfg(feature = "sandbox")] "vendor/github.com/containerd/containerd/api/types/platform.proto", ], diff --git a/crates/shim-protos/src/types.rs b/crates/shim-protos/src/types.rs index a57a6e80..63d8572c 100644 --- a/crates/shim-protos/src/types.rs +++ b/crates/shim-protos/src/types.rs @@ -34,6 +34,9 @@ pub mod fieldpath { include!(concat!(env!("OUT_DIR"), "/types/fieldpath.rs")); } +pub mod introspection { + include!(concat!(env!("OUT_DIR"), "/types/introspection.rs")); +} #[cfg(feature = "sandbox")] pub mod platform { include!(concat!(env!("OUT_DIR"), "/types/platform.rs")); diff --git a/crates/shim-protos/vendor/github.com/containerd/containerd/api/types/introspection.proto b/crates/shim-protos/vendor/github.com/containerd/containerd/api/types/introspection.proto new file mode 100644 index 00000000..8f3fcb5a --- /dev/null +++ b/crates/shim-protos/vendor/github.com/containerd/containerd/api/types/introspection.proto @@ -0,0 +1,46 @@ +/* + 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"; + +option go_package = "github.com/containerd/containerd/api/types;types"; + +message RuntimeRequest { + string runtime_path = 1; + // Options correspond to CreateTaskRequest.options. + // This is needed to pass the runc binary path, etc. + google.protobuf.Any options = 2; +} + +message RuntimeVersion { + string version = 1; + string revision = 2; +} + +message RuntimeInfo { + string name = 1; + RuntimeVersion version = 2; + // Options correspond to RuntimeInfoRequest.Options (contains runc binary path, etc.) + google.protobuf.Any options = 3; + // OCI-compatible runtimes should use https://github.com/opencontainers/runtime-spec/blob/main/features.md + google.protobuf.Any features = 4; + // Annotations of the shim. Irrelevant to features.Annotations. + map annotations = 5; +} diff --git a/crates/shim/Cargo.toml b/crates/shim/Cargo.toml index 468f8edf..df93eb6e 100644 --- a/crates/shim/Cargo.toml +++ b/crates/shim/Cargo.toml @@ -34,6 +34,7 @@ name = "windows-log-reader" path = "examples/windows_log_reader.rs" [dependencies] +which = "7.0.1" containerd-shim-protos = { path = "../shim-protos", version = "0.7.2" } go-flag = "0.1.0" lazy_static = "1.4.0" diff --git a/crates/shim/src/args.rs b/crates/shim/src/args.rs index 09a601d1..11548643 100644 --- a/crates/shim/src/args.rs +++ b/crates/shim/src/args.rs @@ -41,6 +41,8 @@ pub struct Flags { pub action: String, /// Version of the shim. pub version: bool, + /// get the option protobuf from stdin, print the shim info protobuf to stdout, and exit + pub info: bool, } /// Parses command line arguments passed to the shim. @@ -57,6 +59,7 @@ pub fn parse>(args: &[S]) -> Result { f.add_flag("bundle", &mut flags.bundle); f.add_flag("address", &mut flags.address); f.add_flag("publish-binary", &mut flags.publish_binary); + f.add_flag("info", &mut flags.info); }) .map_err(|e| Error::InvalidArgument(e.to_string()))?; diff --git a/crates/shim/src/asynchronous/mod.rs b/crates/shim/src/asynchronous/mod.rs index 4a145310..06e999cf 100644 --- a/crates/shim/src/asynchronous/mod.rs +++ b/crates/shim/src/asynchronous/mod.rs @@ -17,10 +17,10 @@ use std::{ convert::TryFrom, env, + io::Read, os::unix::{fs::FileTypeExt, net::UnixListener}, path::Path, - process, - process::{Command, Stdio}, + process::{self, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -31,9 +31,11 @@ use async_trait::async_trait; use command_fds::{CommandFdExt, FdMapping}; use containerd_shim_protos::{ api::DeleteResponse, - protobuf::Message, + protobuf::{well_known_types::any::Any, Message, MessageField}, + shim::oci::Options, shim_async::{create_task, Client, Task}, ttrpc::r#async::Server, + types::introspection::{self, RuntimeInfo}, }; use futures::StreamExt; use libc::{SIGCHLD, SIGINT, SIGPIPE, SIGTERM}; @@ -46,8 +48,12 @@ use nix::{ }, unistd::Pid, }; +use oci_spec::runtime::Features; use signal_hook_tokio::Signals; use tokio::{io::AsyncWriteExt, sync::Notify}; +use which::which; + +const DEFAULT_BINARY_NAME: &str = "runc"; use crate::{ args, @@ -109,6 +115,48 @@ where process::exit(1); } } +/// get runtime info +pub fn run_info() -> Result { + let mut info = introspection::RuntimeInfo { + name: "containerd-shim-runc-v2-rs".to_string(), + version: MessageField::some(introspection::RuntimeVersion { + version: env!("CARGO_PKG_VERSION").to_string(), + revision: String::default(), + ..Default::default() + }), + ..Default::default() + }; + let mut binary_name = DEFAULT_BINARY_NAME.to_string(); + let mut data: Vec = Vec::new(); + std::io::stdin() + .read_to_end(&mut data) + .map_err(io_error!(e, "read stdin"))?; + // get BinaryName from stdin + if !data.is_empty() { + let opts = + Any::parse_from_bytes(&data).and_then(|any| Options::parse_from_bytes(&any.value))?; + if !opts.binary_name().is_empty() { + binary_name = opts.binary_name().to_string(); + } + } + let binary_path = which(binary_name).unwrap(); + + // get features + let output = Command::new(binary_path).arg("features").output().unwrap(); + + let features: Features = serde_json::from_str(&String::from_utf8_lossy(&output.stdout))?; + + // set features + let features_any = Any { + type_url: "types.containerd.io/opencontainers/runtime-spec/1/features/Features".to_string(), + // features to json + value: serde_json::to_vec(&features)?, + ..Default::default() + }; + info.features = MessageField::some(features_any); + + Ok(info) +} #[cfg_attr(feature = "tracing", tracing::instrument(level = "info"))] async fn bootstrap(runtime_id: &str, opts: Option) -> Result<()>