1pub mod device;
2pub mod host;
3pub mod image;
4pub mod network;
5pub mod zone;
6
7use crate::cli::device::DeviceCommand;
8use crate::cli::host::HostCommand;
9use crate::cli::image::ImageCommand;
10use crate::cli::zone::ZoneCommand;
11use anyhow::{anyhow, Result};
12use clap::Parser;
13use krata::{
14 client::ControlClientProvider,
15 events::EventStream,
16 v1::control::{control_service_client::ControlServiceClient, ResolveZoneIdRequest},
17};
18use network::NetworkCommand;
19use tonic::{transport::Channel, Request};
20
21#[derive(Parser)]
22#[command(version, about = "Control the krata isolation engine")]
23pub struct ControlCommand {
24 #[arg(
25 short,
26 long,
27 help = "The connection URL to the krata isolation engine",
28 default_value = "unix:///var/lib/krata/daemon.socket"
29 )]
30 connection: String,
31
32 #[command(subcommand)]
33 command: ControlCommands,
34}
35
36#[allow(clippy::large_enum_variant)]
37#[derive(Parser)]
38pub enum ControlCommands {
39 Zone(ZoneCommand),
40 Image(ImageCommand),
41 Network(NetworkCommand),
42 Device(DeviceCommand),
43 Host(HostCommand),
44}
45
46impl ControlCommand {
47 pub async fn run(self) -> Result<()> {
48 let client = ControlClientProvider::dial(self.connection.parse()?).await?;
49 let events = EventStream::open(client.clone()).await?;
50 self.command.run(client, events).await
51 }
52}
53
54impl ControlCommands {
55 pub async fn run(
56 self,
57 client: ControlServiceClient<Channel>,
58 events: EventStream,
59 ) -> Result<()> {
60 match self {
61 ControlCommands::Zone(zone) => zone.run(client, events).await,
62
63 ControlCommands::Network(network) => network.run(client, events).await,
64
65 ControlCommands::Image(image) => image.run(client, events).await,
66
67 ControlCommands::Device(device) => device.run(client, events).await,
68
69 ControlCommands::Host(host) => host.run(client, events).await,
70 }
71 }
72}
73
74pub async fn resolve_zone(
75 client: &mut ControlServiceClient<Channel>,
76 name: &str,
77) -> Result<String> {
78 let reply = client
79 .resolve_zone_id(Request::new(ResolveZoneIdRequest {
80 name: name.to_string(),
81 }))
82 .await?
83 .into_inner();
84
85 if !reply.zone_id.is_empty() {
86 Ok(reply.zone_id)
87 } else {
88 Err(anyhow!("unable to resolve zone '{}'", name))
89 }
90}