kratactl/cli/zone/
destroy.rs1use anyhow::Result;
2use clap::Parser;
3use krata::{
4 events::EventStream,
5 v1::control::{
6 control_service_client::ControlServiceClient, watch_events_reply::Event, DestroyZoneRequest,
7 },
8};
9
10use crate::cli::resolve_zone;
11use krata::v1::common::ZoneState;
12use log::error;
13use tonic::{transport::Channel, Request};
14
15#[derive(Parser)]
16#[command(about = "Destroy a zone")]
17pub struct ZoneDestroyCommand {
18 #[arg(
19 short = 'W',
20 long,
21 help = "Wait for the destruction of the zone to complete"
22 )]
23 wait: bool,
24 #[arg(help = "Zone to destroy, either the name or the uuid")]
25 zone: String,
26}
27
28impl ZoneDestroyCommand {
29 pub async fn run(
30 self,
31 mut client: ControlServiceClient<Channel>,
32 events: EventStream,
33 ) -> Result<()> {
34 let zone_id: String = resolve_zone(&mut client, &self.zone).await?;
35 let _ = client
36 .destroy_zone(Request::new(DestroyZoneRequest {
37 zone_id: zone_id.clone(),
38 }))
39 .await?
40 .into_inner();
41 if self.wait {
42 wait_zone_destroyed(&zone_id, events).await?;
43 }
44 Ok(())
45 }
46}
47
48async fn wait_zone_destroyed(id: &str, events: EventStream) -> Result<()> {
49 let mut stream = events.subscribe();
50 while let Ok(event) = stream.recv().await {
51 let Event::ZoneChanged(changed) = event;
52 let Some(zone) = changed.zone else {
53 continue;
54 };
55
56 if zone.id != id {
57 continue;
58 }
59
60 let Some(status) = zone.status else {
61 continue;
62 };
63
64 if let Some(ref error) = status.error_status {
65 if status.state() == ZoneState::Failed {
66 error!("destroy failed: {}", error.message);
67 std::process::exit(1);
68 } else {
69 error!("zone error: {}", error.message);
70 }
71 }
72
73 if status.state() == ZoneState::Destroyed {
74 std::process::exit(0);
75 }
76 }
77 Ok(())
78}