tools: Add Unix socket support to agentl-ctl

Rather than specifying the VSOCK address as two CLI options
(`--vsock-cid` and `--vsock-port`), allow the agent's ttRPC server
address to be specified to the `agent-ctl` tool using a single URI
`--server-address` CLI option. Since the ttrpc crate supports VSOCK and
UNIX schemes, this allows the tool to be run inside the VM by specifying
a UNIX address.

Fixes: #549.

Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
James O. D. Hunt 2020-08-21 16:41:05 +01:00
parent 7be95b15eb
commit 10b1deb274
5 changed files with 176 additions and 96 deletions

View File

@ -8,7 +8,7 @@
use crate::types::{Config, Options}; use crate::types::{Config, Options};
use crate::utils; use crate::utils;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use nix::sys::socket::{connect, socket, AddressFamily, SockAddr, SockFlag, SockType}; use nix::sys::socket::{connect, socket, AddressFamily, SockAddr, SockFlag, SockType, UnixAddr};
use protocols::agent::*; use protocols::agent::*;
use protocols::agent_ttrpc::*; use protocols::agent_ttrpc::*;
use protocols::health::*; use protocols::health::*;
@ -16,7 +16,8 @@ use protocols::health_ttrpc::*;
use slog::{debug, info}; use slog::{debug, info};
use std::io; use std::io;
use std::io::Write; // XXX: for flush() use std::io::Write; // XXX: for flush()
use std::os::unix::io::RawFd; use std::os::unix::io::{IntoRawFd, RawFd};
use std::os::unix::net::UnixStream;
use std::thread::sleep; use std::thread::sleep;
use std::time::Duration; use std::time::Duration;
use ttrpc; use ttrpc;
@ -294,25 +295,123 @@ fn client_create_vsock_fd(cid: libc::c_uint, port: u32) -> Result<RawFd> {
Ok(fd) Ok(fd)
} }
fn create_ttrpc_client(cid: libc::c_uint, port: u32) -> Result<ttrpc::Client> { fn create_ttrpc_client(server_address: String) -> Result<ttrpc::Client> {
let fd = client_create_vsock_fd(cid, port).map_err(|e| { if server_address == "" {
anyhow!(format!( return Err(anyhow!("server address cannot be blank"));
"failed to create VSOCK connection (check agent is running): {:?}", }
e
)) let fields: Vec<&str> = server_address.split("://").collect();
})?;
if fields.len() != 2 {
return Err(anyhow!("invalid server address URI"));
}
let scheme = fields[0].to_lowercase();
let fd: RawFd = match scheme.as_str() {
// Formats:
//
// - "unix://absolute-path" (domain socket)
// (example: "unix:///tmp/domain.socket")
//
// - "unix://@absolute-path" (abstract socket)
// (example: "unix://@/tmp/abstract.socket")
//
"unix" => {
let mut abstract_socket = false;
let mut path = fields[1].to_string();
if path.starts_with('@') {
abstract_socket = true;
// Remove the magic abstract-socket request character ('@')
// and crucially add a trailing nul terminator (required to
// interoperate with the ttrpc crate).
path = path[1..].to_string() + &"\x00".to_string();
}
if abstract_socket {
let socket_fd = match socket(
AddressFamily::Unix,
SockType::Stream,
SockFlag::empty(),
None,
) {
Ok(s) => s,
Err(e) => return Err(anyhow!(e).context("Failed to create Unix Domain socket")),
};
let unix_addr = match UnixAddr::new_abstract(path.as_bytes()) {
Ok(s) => s,
Err(e) => {
return Err(
anyhow!(e).context("Failed to create Unix Domain abstract socket")
)
}
};
let sock_addr = SockAddr::Unix(unix_addr);
connect(socket_fd, &sock_addr).map_err(|e| {
anyhow!(e).context("Failed to connect to Unix Domain abstract socket")
})?;
socket_fd
} else {
let stream = match UnixStream::connect(path) {
Ok(s) => s,
Err(e) => {
return Err(
anyhow!(e).context("failed to create named UNIX Domain stream socket")
)
}
};
stream.into_raw_fd()
}
}
// Format: "vsock://cid:port"
"vsock" => {
let addr: Vec<&str> = fields[1].split(':').collect();
if addr.len() != 2 {
return Err(anyhow!("invalid VSOCK server address URI"));
}
let cid: u32 = match addr[0] {
"-1" | "" => libc::VMADDR_CID_ANY,
_ => match addr[0].parse::<u32>() {
Ok(c) => c,
Err(e) => return Err(anyhow!(e).context("VSOCK CID is not numeric")),
},
};
let port: u32 = match addr[1].parse::<u32>() {
Ok(r) => r,
Err(e) => return Err(anyhow!(e).context("VSOCK port is not numeric")),
};
client_create_vsock_fd(cid, port).map_err(|e| {
anyhow!(e).context("failed to create VSOCK connection (check agent is running)")
})?
}
_ => {
return Err(anyhow!("invalid server address URI scheme: {:?}", scheme));
}
};
Ok(ttrpc::client::Client::new(fd)) Ok(ttrpc::client::Client::new(fd))
} }
fn kata_service_agent(cid: libc::c_uint, port: u32) -> Result<AgentServiceClient> { fn kata_service_agent(server_address: String) -> Result<AgentServiceClient> {
let ttrpc_client = create_ttrpc_client(cid, port)?; let ttrpc_client = create_ttrpc_client(server_address)?;
Ok(AgentServiceClient::new(ttrpc_client)) Ok(AgentServiceClient::new(ttrpc_client))
} }
fn kata_service_health(cid: libc::c_uint, port: u32) -> Result<HealthClient> { fn kata_service_health(server_address: String) -> Result<HealthClient> {
let ttrpc_client = create_ttrpc_client(cid, port)?; let ttrpc_client = create_ttrpc_client(server_address)?;
Ok(HealthClient::new(ttrpc_client)) Ok(HealthClient::new(ttrpc_client))
} }
@ -344,15 +443,10 @@ pub fn client(cfg: &Config, commands: Vec<&str>) -> Result<()> {
announce(cfg); announce(cfg);
let cid = cfg.cid;
let port = cfg.port;
let addr = format!("vsock://{}:{}", cid, port);
// Create separate connections for each of the services provided // Create separate connections for each of the services provided
// by the agent. // by the agent.
let client = kata_service_agent(cid, port as u32)?; let client = kata_service_agent(cfg.server_address.clone())?;
let health = kata_service_health(cid, port as u32)?; let health = kata_service_health(cfg.server_address.clone())?;
let mut options = Options::new(); let mut options = Options::new();
@ -365,7 +459,7 @@ pub fn client(cfg: &Config, commands: Vec<&str>) -> Result<()> {
options.insert("bundle-dir".to_string(), cfg.bundle_dir.clone()); options.insert("bundle-dir".to_string(), cfg.bundle_dir.clone());
info!(sl!(), "client setup complete"; info!(sl!(), "client setup complete";
"server-address" => addr); "server-address" => cfg.server_address.to_string());
if cfg.interactive { if cfg.interactive {
return interactive_client_loop(&cfg, &mut options, &client, &health); return interactive_client_loop(&cfg, &mut options, &client, &health);
@ -533,8 +627,8 @@ fn interactive_client_loop(
let mut repeat_count: i64 = 1; let mut repeat_count: i64 = 1;
loop { loop {
let cmdline = readline("Enter command") let cmdline =
.map_err(|e| anyhow!(format!("failed to read line: {}", e)))?; readline("Enter command").map_err(|e| anyhow!(e).context("failed to read line"))?;
if cmdline == "" { if cmdline == "" {
continue; continue;
@ -592,7 +686,7 @@ fn agent_cmd_health_check(
let reply = health let reply = health
.check(&req, cfg.timeout_nano) .check(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -615,7 +709,7 @@ fn agent_cmd_health_version(
let reply = health let reply = health
.version(&req, cfg.timeout_nano) .version(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -637,7 +731,7 @@ fn agent_cmd_sandbox_create(
let reply = client let reply = client
.create_sandbox(&req, cfg.timeout_nano) .create_sandbox(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -656,7 +750,7 @@ fn agent_cmd_sandbox_destroy(
let reply = client let reply = client
.destroy_sandbox(&req, cfg.timeout_nano) .destroy_sandbox(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -686,7 +780,7 @@ fn agent_cmd_container_create(
let reply = client let reply = client
.create_container(&req, cfg.timeout_nano) .create_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -709,7 +803,7 @@ fn agent_cmd_container_remove(
let reply = client let reply = client
.remove_container(&req, cfg.timeout_nano) .remove_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -746,7 +840,7 @@ fn agent_cmd_container_exec(
let reply = client let reply = client
.exec_process(&req, cfg.timeout_nano) .exec_process(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -769,7 +863,7 @@ fn agent_cmd_container_stats(
let reply = client let reply = client
.stats_container(&req, cfg.timeout_nano) .stats_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -792,7 +886,7 @@ fn agent_cmd_container_pause(
let reply = client let reply = client
.pause_container(&req, cfg.timeout_nano) .pause_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -815,7 +909,7 @@ fn agent_cmd_container_resume(
let reply = client let reply = client
.resume_container(&req, cfg.timeout_nano) .resume_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -838,7 +932,7 @@ fn agent_cmd_container_start(
let reply = client let reply = client
.start_container(&req, cfg.timeout_nano) .start_container(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -859,7 +953,7 @@ fn agent_cmd_sandbox_guest_details(
let reply = client let reply = client
.get_guest_details(&req, cfg.timeout_nano) .get_guest_details(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -889,7 +983,7 @@ fn agent_cmd_container_list_processes(
let reply = client let reply = client
.list_processes(&req, cfg.timeout_nano) .list_processes(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -914,7 +1008,7 @@ fn agent_cmd_container_wait_process(
let reply = client let reply = client
.wait_process(&req, cfg.timeout_nano) .wait_process(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -949,7 +1043,7 @@ fn agent_cmd_container_signal_process(
let reply = client let reply = client
.signal_process(&req, cfg.timeout_nano) .signal_process(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -968,7 +1062,7 @@ fn agent_cmd_sandbox_tracing_start(
let reply = client let reply = client
.start_tracing(&req, cfg.timeout_nano) .start_tracing(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -987,7 +1081,7 @@ fn agent_cmd_sandbox_tracing_stop(
let reply = client let reply = client
.stop_tracing(&req, cfg.timeout_nano) .stop_tracing(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -1006,7 +1100,7 @@ fn agent_cmd_sandbox_update_interface(
let reply = client let reply = client
.update_interface(&req, cfg.timeout_nano) .update_interface(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
// FIXME: Implement 'UpdateInterface' fully. // FIXME: Implement 'UpdateInterface' fully.
eprintln!("FIXME: 'UpdateInterface' not fully implemented"); eprintln!("FIXME: 'UpdateInterface' not fully implemented");
@ -1031,7 +1125,7 @@ fn agent_cmd_sandbox_update_routes(
let reply = client let reply = client
.update_routes(&req, cfg.timeout_nano) .update_routes(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
// FIXME: Implement 'UpdateRoutes' fully. // FIXME: Implement 'UpdateRoutes' fully.
eprintln!("FIXME: 'UpdateRoutes' not fully implemented"); eprintln!("FIXME: 'UpdateRoutes' not fully implemented");
@ -1056,7 +1150,7 @@ fn agent_cmd_sandbox_list_interfaces(
let reply = client let reply = client
.list_interfaces(&req, cfg.timeout_nano) .list_interfaces(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));
@ -1075,7 +1169,7 @@ fn agent_cmd_sandbox_list_routes(
let reply = client let reply = client
.list_routes(&req, cfg.timeout_nano) .list_routes(&req, cfg.timeout_nano)
.map_err(|e| anyhow!(format!("{}: {:?}", ERR_API_FAILED, e)))?; .map_err(|e| anyhow!("{:?}", e).context(ERR_API_FAILED))?;
info!(sl!(), "response received"; info!(sl!(), "response received";
"response" => format!("{:?}", reply)); "response" => format!("{:?}", reply));

View File

@ -40,27 +40,36 @@ const WARNING_TEXT: &str = r#"WARNING:
sandbox."#; sandbox."#;
fn make_examples_text(program_name: &str) -> String { fn make_examples_text(program_name: &str) -> String {
let abstract_server_address = "unix://@/foo/bar/abstract.socket";
let bundle = "$bundle_dir"; let bundle = "$bundle_dir";
let cid = 3;
let container_id = "$container_id";
let config_file_uri = "file:///tmp/config.json"; let config_file_uri = "file:///tmp/config.json";
let port = 1024; let container_id = "$container_id";
let local_server_address = "unix:///tmp/local.socket";
let sandbox_id = "$sandbox_id"; let sandbox_id = "$sandbox_id";
let vsock_server_address = "vsock://3:1024";
format!( format!(
r#"EXAMPLES: r#"EXAMPLES:
- Check if the agent is running: - Check if the agent is running:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd Check $ {program} connect --server-address "{vsock_server_address}" --cmd Check
- Connect to the agent using local sockets (when running in same environment as the agent):
# Local socket
$ {program} connect --server-address "{local_server_address}" --cmd Check
# Abstract socket
$ {program} connect --server-address "{abstract_server_address}" --cmd Check
- Query the agent environment: - Query the agent environment:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd GuestDetails $ {program} connect --server-address "{vsock_server_address}" --cmd GuestDetails
- List all available (built-in and Kata Agent API) commands: - List all available (built-in and Kata Agent API) commands:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd list $ {program} connect --server-address "{vsock_server_address}" --cmd list
- Generate a random container ID: - Generate a random container ID:
@ -72,33 +81,34 @@ fn make_examples_text(program_name: &str) -> String {
- Attempt to create 7 sandboxes, ignoring any errors: - Attempt to create 7 sandboxes, ignoring any errors:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --repeat 7 --cmd CreateSandbox $ {program} connect --server-address "{vsock_server_address}" --repeat 7 --cmd CreateSandbox
- Query guest details forever: - Query guest details forever:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --repeat -1 --cmd GuestDetails $ {program} connect --server-address "{vsock_server_address}" --repeat -1 --cmd GuestDetails
- Send a 'SIGUSR1' signal to a container process: - Send a 'SIGUSR1' signal to a container process:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd 'SignalProcess signal=usr1 sid={sandbox_id} cid={container_id}' $ {program} connect --server-address "{vsock_server_address}" --cmd 'SignalProcess signal=usr1 sid={sandbox_id} cid={container_id}'
- Create a sandbox with a single container, and then destroy everything: - Create a sandbox with a single container, and then destroy everything:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd CreateSandbox $ {program} connect --server-address "{vsock_server_address}" --cmd CreateSandbox
$ {program} connect --vsock-cid {cid} --vsock-port {port} --bundle-dir {bundle:?} --cmd CreateContainer $ {program} connect --server-address "{vsock_server_address}" --bundle-dir {bundle:?} --cmd CreateContainer
$ {program} connect --vsock-cid {cid} --vsock-port {port} --cmd DestroySandbox $ {program} connect --server-address "{vsock_server_address}" --cmd DestroySandbox
- Create a Container using a custom configuration file: - Create a Container using a custom configuration file:
$ {program} connect --vsock-cid {cid} --vsock-port {port} --bundle-dir {bundle:?} --cmd 'CreateContainer spec={config_file_uri}' $ {program} connect --server-address "{vsock_server_address}" --bundle-dir {bundle:?} --cmd 'CreateContainer spec={config_file_uri}'
"#, "#,
abstract_server_address = abstract_server_address,
bundle = bundle, bundle = bundle,
cid = cid,
config_file_uri = config_file_uri, config_file_uri = config_file_uri,
container_id = container_id, container_id = container_id,
port = port, local_server_address = local_server_address,
program = program_name, program = program_name,
sandbox_id = sandbox_id, sandbox_id = sandbox_id,
vsock_server_address = vsock_server_address,
) )
} }
@ -111,24 +121,11 @@ fn connect(name: &str, global_args: clap::ArgMatches) -> Result<()> {
let interactive = args.is_present("interactive"); let interactive = args.is_present("interactive");
let ignore_errors = args.is_present("ignore-errors"); let ignore_errors = args.is_present("ignore-errors");
let cid_str = args let server_address = args
.value_of("vsock-cid") .value_of("server-address")
.ok_or("need VSOCK cid".to_string()) .ok_or("need server adddress".to_string())
.map_err(|e| anyhow!(e))?; .map_err(|e| anyhow!(e))?;
let port_str = args
.value_of("vsock-port")
.ok_or("need VSOCK port number".to_string())
.map_err(|e| anyhow!(e))?;
let cid: u32 = cid_str
.parse::<u32>()
.map_err(|e| anyhow!(format!("invalid VSOCK CID number: {}", e.to_string())))?;
let port: u32 = port_str
.parse::<u32>()
.map_err(|e| anyhow!(format!("invalid VSOCK port number: {}", e)))?;
let mut commands: Vec<&str> = Vec::new(); let mut commands: Vec<&str> = Vec::new();
if !interactive { if !interactive {
@ -156,8 +153,7 @@ fn connect(name: &str, global_args: clap::ArgMatches) -> Result<()> {
let result = rpc::run( let result = rpc::run(
&logger, &logger,
cid, server_address,
port,
bundle_dir, bundle_dir,
interactive, interactive,
ignore_errors, ignore_errors,
@ -200,13 +196,6 @@ fn real_main() -> Result<()> {
.takes_value(true) .takes_value(true)
.value_name("directory"), .value_name("directory"),
) )
.arg(
Arg::with_name("vsock-cid")
.long("vsock-cid")
.help("VSOCK Context ID")
.takes_value(true)
.value_name("CID"),
)
.arg( .arg(
Arg::with_name("cmd") Arg::with_name("cmd")
.long("cmd") .long("cmd")
@ -227,11 +216,11 @@ fn real_main() -> Result<()> {
.help("Allow interactive client"), .help("Allow interactive client"),
) )
.arg( .arg(
Arg::with_name("vsock-port") Arg::with_name("server-address")
.long("vsock-port") .long("server-address")
.help("VSOCK Port number") .help("server URI (vsock:// or unix://)")
.takes_value(true) .takes_value(true)
.value_name("port-number"), .value_name("URI"),
) )
.arg( .arg(
Arg::with_name("timeout") Arg::with_name("timeout")

View File

@ -13,8 +13,7 @@ use crate::types::Config;
pub fn run( pub fn run(
logger: &Logger, logger: &Logger,
cid: u32, server_address: &str,
port: u32,
bundle_dir: &str, bundle_dir: &str,
interactive: bool, interactive: bool,
ignore_errors: bool, ignore_errors: bool,
@ -22,8 +21,7 @@ pub fn run(
commands: Vec<&str>, commands: Vec<&str>,
) -> Result<()> { ) -> Result<()> {
let cfg = Config { let cfg = Config {
cid: cid, server_address: server_address.to_string(),
port: port,
bundle_dir: bundle_dir.to_string(), bundle_dir: bundle_dir.to_string(),
timeout_nano: timeout_nano, timeout_nano: timeout_nano,
interactive: interactive, interactive: interactive,

View File

@ -11,8 +11,7 @@ pub type Options = HashMap<String, String>;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config { pub struct Config {
pub cid: u32, pub server_address: String,
pub port: u32,
pub bundle_dir: String, pub bundle_dir: String,
pub timeout_nano: i64, pub timeout_nano: i64,
pub interactive: bool, pub interactive: bool,

View File

@ -250,7 +250,7 @@ fn config_file_from_bundle_dir(bundle_dir: &str) -> Result<String> {
config_path config_path
.into_os_string() .into_os_string()
.into_string() .into_string()
.map_err(|e| anyhow!(format!("failed to construct config file path: {:?}", e))) .map_err(|e| anyhow!("{:?}", e).context("failed to construct config file path"))
} }
fn root_oci_to_grpc(bundle_dir: &str, root: &ociRoot) -> Result<grpcRoot> { fn root_oci_to_grpc(bundle_dir: &str, root: &ociRoot) -> Result<grpcRoot> {
@ -265,7 +265,7 @@ fn root_oci_to_grpc(bundle_dir: &str, root: &ociRoot) -> Result<grpcRoot> {
abs_root_dir abs_root_dir
.into_os_string() .into_os_string()
.into_string() .into_string()
.map_err(|e| anyhow!(format!("failed to construct bundle path: {:?}", e)))? .map_err(|e| anyhow!("{:?}", e).context("failed to construct bundle path"))?
}; };
let grpc_root = grpcRoot { let grpc_root = grpcRoot {