diff --git a/src/tools/runk/Cargo.lock b/src/tools/runk/Cargo.lock index f8628cbf7..a1691a796 100644 --- a/src/tools/runk/Cargo.lock +++ b/src/tools/runk/Cargo.lock @@ -985,7 +985,9 @@ dependencies = [ "serde_json", "slog", "slog-async", + "tabwriter", "tokio", + "users", ] [[package]] @@ -1166,6 +1168,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tabwriter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36205cfc997faadcc4b0b87aaef3fbedafe20d38d4959a7ca6ff803564051111" +dependencies = [ + "unicode-width", +] + [[package]] name = "take_mut" version = "0.2.2" @@ -1348,12 +1359,28 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "unicode-xid" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "users" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" +dependencies = [ + "libc", + "log", +] + [[package]] name = "version_check" version = "0.9.4" diff --git a/src/tools/runk/Cargo.toml b/src/tools/runk/Cargo.toml index 83aca82ca..973ae21c7 100644 --- a/src/tools/runk/Cargo.toml +++ b/src/tools/runk/Cargo.toml @@ -22,6 +22,8 @@ slog-async = "2.7.0" tokio = { version = "1.15.0", features = ["full"] } serde = { version = "1.0.133", features = ["derive"] } serde_json = "1.0.74" +users = "0.11.0" +tabwriter = "1.2.1" [workspace] members = [ diff --git a/src/tools/runk/src/commands/list.rs b/src/tools/runk/src/commands/list.rs new file mode 100644 index 000000000..dbd427755 --- /dev/null +++ b/src/tools/runk/src/commands/list.rs @@ -0,0 +1,69 @@ +// Copyright 2021-2022 Kata Contributors +// +// SPDX-License-Identifier: Apache-2.0 +// + +use super::state::get_container_state_name; +use anyhow::Result; +use libcontainer::status::{get_current_container_state, Status}; +use liboci_cli::List; +use oci::ContainerState; +use slog::{info, Logger}; +use std::{fs, os::unix::prelude::MetadataExt, path::Path}; +use std::{io, io::Write}; +use tabwriter::TabWriter; +use users::get_user_by_uid; + +pub fn run(_: List, root: &Path, logger: &Logger) -> Result<()> { + let mut content = String::new(); + for entry in fs::read_dir(root)? { + let entry = entry?; + // Possibly race with runk delete, so continue loop when any error occurs below + let metadata = match entry.metadata() { + Ok(metadata) => metadata, + Err(_) => continue, + }; + if !metadata.is_dir() { + continue; + } + let container_id = match entry.file_name().into_string() { + Ok(id) => id, + Err(_) => continue, + }; + let status = match Status::load(root, &container_id) { + Ok(status) => status, + Err(_) => continue, + }; + let state = match get_current_container_state(&status) { + Ok(state) => state, + Err(_) => continue, + }; + // Just like runc, pid of stopped container is 0 + let pid = match state { + ContainerState::Stopped => 0, + _ => status.pid, + }; + // May replace get_user_by_uid with getpwuid(3) + let owner = match get_user_by_uid(metadata.uid()) { + Some(user) => String::from(user.name().to_string_lossy()), + None => format!("#{}", metadata.uid()), + }; + content.push_str(&format!( + "{}\t{}\t{}\t{}\t{}\t{}\n", + container_id, + pid, + get_container_state_name(state), + status.bundle.display(), + status.created, + owner + )); + } + + let mut tab_writer = TabWriter::new(io::stdout()); + writeln!(&mut tab_writer, "ID\tPID\tSTATUS\tBUNDLE\tCREATED\tOWNER")?; + write!(&mut tab_writer, "{}", content)?; + tab_writer.flush()?; + + info!(&logger, "list command finished successfully"); + Ok(()) +} diff --git a/src/tools/runk/src/commands/mod.rs b/src/tools/runk/src/commands/mod.rs index 12017263d..216686506 100644 --- a/src/tools/runk/src/commands/mod.rs +++ b/src/tools/runk/src/commands/mod.rs @@ -6,6 +6,7 @@ pub mod create; pub mod delete; pub mod kill; +pub mod list; pub mod run; pub mod spec; pub mod start; diff --git a/src/tools/runk/src/main.rs b/src/tools/runk/src/main.rs index 8f464f438..0171a229f 100644 --- a/src/tools/runk/src/main.rs +++ b/src/tools/runk/src/main.rs @@ -78,6 +78,7 @@ async fn cmd_run(subcmd: SubCommand, root_path: &Path, logger: &Logger) -> Resul SubCommand::Common(cmd) => match cmd { CommonCmd::Run(run) => commands::run::run(run, root_path, logger).await, CommonCmd::Spec(spec) => commands::spec::run(spec, logger), + CommonCmd::List(list) => commands::list::run(list, root_path, logger), _ => { return Err(anyhow!("command is not implemented yet")); }