summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <matthias.beyer@atos.net>2021-06-22 17:45:33 +0200
committerMatthias Beyer <matthias.beyer@atos.net>2021-06-23 08:21:52 +0200
commit707898fe04354001130f02a68e1443288d85af3f (patch)
tree0332a5d20921e06dce035cbf009cdb1243e05a4e
parentc84f183867da4423d219b65474e9271b33128a63 (diff)
Add implementation of "endpoint images" subcommand
Signed-off-by: Matthias Beyer <matthias.beyer@atos.net>
-rw-r--r--src/commands/endpoint.rs88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/commands/endpoint.rs b/src/commands/endpoint.rs
index 6fd7d69..cd65887 100644
--- a/src/commands/endpoint.rs
+++ b/src/commands/endpoint.rs
@@ -11,6 +11,7 @@
//! Implementation of the 'endpoint' subcommand
use std::collections::HashMap;
+use std::io::Write;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
@@ -49,6 +50,7 @@ pub async fn endpoint(matches: &ArgMatches, config: &Configuration, progress_gen
Some(("stats", matches)) => stats(endpoint_names, matches, config, progress_generator).await,
Some(("container", matches)) => crate::commands::endpoint_container::container(endpoint_names, matches, config).await,
Some(("containers", matches)) => containers(endpoint_names, matches, config).await,
+ Some(("images", matches)) => images(endpoint_names, matches, config).await,
Some((other, _)) => Err(anyhow!("Unknown subcommand: {}", other)),
None => Err(anyhow!("No subcommand")),
}
@@ -422,6 +424,92 @@ async fn containers_stop(endpoint_names: Vec<EndpointName>,
}
+async fn images(endpoint_names: Vec<EndpointName>,
+ matches: &ArgMatches,
+ config: &Configuration,
+) -> Result<()> {
+ match matches.subcommand() {
+ Some(("list", matches)) => images_list(endpoint_names, matches, config).await,
+ Some(("verify-present", matches)) => images_present(endpoint_names, matches, config).await,
+ Some((other, _)) => Err(anyhow!("Unknown subcommand: {}", other)),
+ None => Err(anyhow!("No subcommand")),
+ }
+}
+
+async fn images_list(endpoint_names: Vec<EndpointName>,
+ _matches: &ArgMatches,
+ config: &Configuration,
+) -> Result<()> {
+ let mut iter = connect_to_endpoints(config, &endpoint_names)
+ .await?
+ .into_iter()
+ .map(move |ep| async move { ep.images(None).await })
+ .collect::<futures::stream::FuturesUnordered<_>>()
+ .collect::<Result<Vec<_>>>()
+ .await?
+ .into_iter()
+ .flatten();
+
+ let out = std::io::stdout();
+ let mut lock = out.lock();
+
+ iter.try_for_each(|img| {
+ writeln!(lock, "{created} {id}", created = img.created(), id = {
+ if let Some(tags)= img.tags() {
+ tags.join(", ")
+ } else {
+ img.id().clone()
+ }
+ }).map_err(Error::from)
+ })
+}
+
+async fn images_present(endpoint_names: Vec<EndpointName>,
+ _matches: &ArgMatches,
+ config: &Configuration,
+) -> Result<()> {
+ use crate::util::docker::ImageName;
+
+ let eps = connect_to_endpoints(config, &endpoint_names).await?;
+
+ let ep_names_to_images = eps.iter()
+ .map(|ep| async move {
+ ep.images(None).await.map(|imgs| {
+ let img_tags = imgs.filter_map(|img| img.tags().clone().map(Vec::into_iter))
+ .flatten()
+ .map(ImageName::from)
+ .collect();
+
+ (ep.name().clone(), img_tags)
+ })
+ })
+ .collect::<futures::stream::FuturesUnordered<_>>()
+ .collect::<Result<Vec<(EndpointName, Vec<ImageName>)>>>()
+ .await?
+ .into_iter()
+ .collect::<HashMap<EndpointName, Vec<ImageName>>>();
+
+ let out = std::io::stdout();
+ let mut lock = out.lock();
+
+ ep_names_to_images
+ .iter()
+ .map(|(ep_name, ep_imgs)| {
+ config.docker()
+ .images()
+ .iter()
+ .map(|config_img| (ep_imgs.contains(config_img), config_img))
+ .try_for_each(|(found, img_name)| {
+ if found {
+ writeln!(lock, "found {img} in {ep}", img = img_name, ep = ep_name).map_err(Error::from)
+ } else {
+ writeln!(lock, "{img} not found", img = img_name).map_err(Error::from)
+ }
+ })
+ })
+ .collect::<Result<()>>()
+}
+
/// Helper function to connect to all endpoints from the configuration, that appear (by name) in
/// the `endpoint_names` list
pub(super) async fn connect_to_endpoints(config: &Configuration, endpoint_names: &[EndpointName]) -> Result<Vec<Arc<Endpoint>>> {