seaplane_cli/cli/cmds/formation/
status.rs1use clap::{value_parser, ArgMatches, Command};
2
3use crate::{
4 api::FormationsReq,
5 cli::{
6 cmds::formation::SeaplaneFormationFetch,
7 validator::{validate_formation_name, validate_name_id},
8 CliCommand,
9 },
10 error::Result,
11 ops::formation::FormationStatus,
12 printer::{Output, Pb},
13 Ctx, OutputFormat,
14};
15
16static LONG_ABOUT: &str = "Show the status of a remote Formation Instance
17
18This command will display the status of one or more Formation Instances such as how many actual
19containers are running compared to the minimum and maximums per Flight Plan that the configuration
20defines.";
21
22#[derive(Copy, Clone, Debug)]
23pub struct SeaplaneFormationStatus;
24
25impl SeaplaneFormationStatus {
26 pub fn command() -> Command {
27 let validator = |s: &str| validate_name_id(validate_formation_name, s);
28 Command::new("status")
29 .long_about(LONG_ABOUT)
30 .about("Show the status of a remote Formation Instance")
31 .arg(
32 arg!(formation = ["NAME|ID"])
33 .value_parser(validator)
34 .help("The name or ID of the Formation to check, must be unambiguous"),
35 )
36 .arg(
37 arg!(--format =["FORMAT"=>"table"])
38 .value_parser(value_parser!(OutputFormat))
39 .help("Change the output format"),
40 )
41 .arg(arg!(--("no-fetch")).help("Skip fetching and synchronizing of remote instances"))
42 }
43}
44
45impl CliCommand for SeaplaneFormationStatus {
46 fn run(&self, ctx: &mut Ctx) -> Result<()> {
47 let old_stateless = ctx.args.stateless;
48
49 if ctx.args.fetch {
50 ctx.internal_run = true;
54 ctx.disable_pb = ctx.args.out_format == OutputFormat::Json;
55 ctx.args.stateless = true;
56 let old_name = ctx.args.name_id.take();
57 SeaplaneFormationFetch.run(ctx)?;
58 ctx.args.name_id = old_name;
59 ctx.internal_run = false;
60 ctx.args.stateless = old_stateless;
61 }
62
63 let pb = Pb::new(ctx);
64
65 let names = if let Some(name) = ctx.args.name_id.as_deref() {
66 vec![name]
67 } else {
68 ctx.db.formations.remote_names()
69 };
70
71 let mut statuses: Vec<FormationStatus> = Vec::new();
72
73 let mut req = FormationsReq::new_delay_token(ctx)?;
74 for name in names {
75 pb.set_message(format!("Gathering {name} container info..."));
76 req.set_name(name)?;
77 let mut f_status = FormationStatus::new(name);
78 for container in req.get_containers()?.iter() {
79 if let Some(cfg) = ctx
80 .db
81 .formations
82 .get_configuration_by_uuid(container.configuration_id)
83 {
84 if let Some(flight) = cfg.get_flight(&container.flight_name) {
85 f_status.add_container(container, flight.minimum(), flight.maximum());
86 }
87 }
88 }
89 f_status.update_status();
91 statuses.push(f_status);
92 }
93
94 pb.finish_and_clear();
95
96 match ctx.args.out_format {
97 OutputFormat::Json => statuses.print_json(ctx)?,
98 OutputFormat::Table => statuses.print_table(ctx)?,
99 }
100
101 Ok(())
102 }
103
104 fn update_ctx(&self, matches: &ArgMatches, ctx: &mut Ctx) -> Result<()> {
105 ctx.args.out_format = matches.get_one("format").copied().unwrap_or_default();
106 ctx.args.name_id = matches
107 .get_one::<String>("formation")
108 .map(ToOwned::to_owned);
109 ctx.args.fetch = !matches.get_flag("no-fetch");
110 Ok(())
111 }
112}