summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <matthias.beyer@atos.net>2021-03-05 16:17:25 +0100
committerMatthias Beyer <mail@beyermatthias.de>2021-03-07 21:50:29 +0100
commit3d8dc565f9de9466f0e049d28101e6a1d64bba17 (patch)
tree4cc039c4ddea97883a7ac81819918e429f7c1277
parent161dbe6b8c479128f3092e8b7c3449c39be27986 (diff)
Add "endpoint stats" subcommand
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
-rw-r--r--src/cli.rs11
-rw-r--r--src/commands/endpoint.rs84
2 files changed, 95 insertions, 0 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 2aacc98..d079a70 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -865,6 +865,17 @@ pub fn cli<'a>() -> App<'a> {
.about("How long to sleep between pings")
)
)
+ .subcommand(App::new("stats")
+ .version(crate_version!())
+ .about("Get stats for the endpoint(s)")
+ .arg(Arg::new("csv")
+ .required(false)
+ .multiple(false)
+ .long("csv")
+ .takes_value(false)
+ .about("Format output as CSV")
+ )
+ )
)
}
diff --git a/src/commands/endpoint.rs b/src/commands/endpoint.rs
index fb98c6a..128613a 100644
--- a/src/commands/endpoint.rs
+++ b/src/commands/endpoint.rs
@@ -37,6 +37,7 @@ pub async fn endpoint(matches: &ArgMatches, config: &Configuration, progress_gen
match matches.subcommand() {
Some(("ping", matches)) => ping(endpoint_names, matches, config, progress_generator).await,
+ Some(("stats", matches)) => stats(endpoint_names, matches, config, progress_generator).await,
Some((other, _)) => Err(anyhow!("Unknown subcommand: {}", other)),
None => Err(anyhow!("No subcommand")),
}
@@ -111,3 +112,86 @@ async fn ping(endpoint_names: Vec<String>,
let multibar_block = tokio::task::spawn_blocking(move || multibar.join());
tokio::join!(ping_process, multibar_block).0
}
+
+async fn stats(endpoint_names: Vec<String>,
+ matches: &ArgMatches,
+ config: &Configuration,
+ progress_generator: ProgressBars
+) -> Result<()> {
+ let csv = matches.is_present("csv");
+
+ let endpoint_configurations = config
+ .docker()
+ .endpoints()
+ .iter()
+ .filter(|ep| endpoint_names.contains(ep.name()))
+ .cloned()
+ .map(|ep_cfg| {
+ crate::endpoint::EndpointConfiguration::builder()
+ .endpoint(ep_cfg)
+ .required_images(config.docker().images().clone())
+ .required_docker_versions(config.docker().docker_versions().clone())
+ .required_docker_api_versions(config.docker().docker_api_versions().clone())
+ .build()
+ })
+ .collect::<Vec<_>>();
+
+ info!("Endpoint config build");
+ info!("Connecting to {n} endpoints: {eps}",
+ n = endpoint_configurations.len(),
+ eps = endpoint_configurations.iter().map(|epc| epc.endpoint().name()).join(", "));
+
+ let bar = progress_generator.bar();
+ bar.set_length(endpoint_configurations.len() as u64);
+ bar.set_message("Fetching stats");
+
+ let endpoints = crate::endpoint::util::setup_endpoints(endpoint_configurations).await?;
+
+ let hdr = crate::commands::util::mk_header([
+ "Name",
+ "Containers",
+ "Images",
+ "Kernel",
+ "Memory",
+ "Memory limit",
+ "Cores",
+ "OS",
+ "System Time",
+ ].to_vec());
+
+ let data = endpoints
+ .into_iter()
+ .map(|endpoint| {
+ let bar = bar.clone();
+ async move {
+ let r = endpoint.stats().await;
+ bar.inc(1);
+ r
+ }
+ })
+ .collect::<futures::stream::FuturesUnordered<_>>()
+ .collect::<Result<Vec<_>>>()
+ .await
+ .map_err(|e| {
+ bar.finish_with_message("Fetching stats errored");
+ e
+ })?
+ .into_iter()
+ .map(|stat| {
+ vec![
+ stat.name,
+ stat.containers.to_string(),
+ stat.images.to_string(),
+ stat.kernel_version,
+ stat.mem_total.to_string(),
+ stat.memory_limit.to_string(),
+ stat.n_cpu.to_string(),
+ stat.operating_system.to_string(),
+ stat.system_time.map(|t| t.to_string()).unwrap_or_else(|| String::from("unknown")),
+ ]
+ })
+ .collect();
+
+ bar.finish_with_message("Fetching stats successful");
+ crate::commands::util::display_data(hdr, data, csv)
+}