From 608bc1908ff02ecce1309853a575f0d97871dee4 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Fri, 21 Jun 2024 13:28:57 -0400 Subject: [PATCH] export: Add progress flag This is a very slow operation and it'd be really nice to have progress. Unfortunately we don't have a sane way to propagate status from `skopeo copy`, so add an option to just output to stdout, which is usable now in bootc. Signed-off-by: Colin Walters --- lib/src/container/encapsulate.rs | 1 + lib/src/container/skopeo.rs | 6 +++++- lib/src/container/store.rs | 8 ++++++-- lib/src/container/update_detachedmeta.rs | 4 ++-- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/src/container/encapsulate.rs b/lib/src/container/encapsulate.rs index d61355b33..3f055f4fa 100644 --- a/lib/src/container/encapsulate.rs +++ b/lib/src/container/encapsulate.rs @@ -330,6 +330,7 @@ async fn build_impl( dest, authfile.as_deref(), Some((std::sync::Arc::new(tempdir.try_clone()?.into()), target_fd)), + false, ) .await?; Some(digest) diff --git a/lib/src/container/skopeo.rs b/lib/src/container/skopeo.rs index aa18333fb..20537689f 100644 --- a/lib/src/container/skopeo.rs +++ b/lib/src/container/skopeo.rs @@ -67,10 +67,14 @@ pub(crate) async fn copy( dest: &ImageReference, authfile: Option<&Path>, add_fd: Option<(std::sync::Arc, i32)>, + progress: bool, ) -> Result { let digestfile = tempfile::NamedTempFile::new()?; let mut cmd = new_cmd(); - cmd.stdout(std::process::Stdio::null()).arg("copy"); + cmd.arg("copy"); + if !progress { + cmd.stdout(std::process::Stdio::null()); + } cmd.arg("--digestfile"); cmd.arg(digestfile.path()); if let Some((add_fd, n)) = add_fd { diff --git a/lib/src/container/store.rs b/lib/src/container/store.rs index 084ab9a46..49d2ca659 100644 --- a/lib/src/container/store.rs +++ b/lib/src/container/store.rs @@ -1221,6 +1221,8 @@ pub struct ExportToOCIOpts { pub skip_compression: bool, /// Path to Docker-formatted authentication file. pub authfile: Option, + /// Output progress to stdout + pub progress_to_stdout: bool, } /// The way we store "chunk" layers in ostree is by writing a commit @@ -1358,6 +1360,7 @@ pub async fn export( dest_imgref: &ImageReference, opts: Option, ) -> Result { + let opts = opts.unwrap_or_default(); let target_oci = dest_imgref.transport == Transport::OciDir; let tempdir = if !target_oci { let vartmp = cap_std::fs::Dir::open_ambient_dir("/var/tmp", cap_std::ambient_authority())?; @@ -1365,12 +1368,12 @@ pub async fn export( // Always skip compression when making a temporary copy let opts = ExportToOCIOpts { skip_compression: true, + progress_to_stdout: opts.progress_to_stdout, ..Default::default() }; export_to_oci(repo, src_imgref, &td, None, opts)?; td } else { - let opts = opts.unwrap_or_default(); let (path, tag) = parse_oci_path_and_tag(dest_imgref.name.as_str()); tracing::debug!("using OCI path={path} tag={tag:?}"); let path = Dir::open_ambient_dir(path, cap_std::ambient_authority()) @@ -1384,12 +1387,13 @@ pub async fn export( transport: Transport::OciDir, name: format!("/proc/self/fd/{target_fd}"), }; - let authfile = opts.as_ref().and_then(|o| o.authfile.as_deref()); + let authfile = opts.authfile.as_deref(); skopeo::copy( &tempoci, dest_imgref, authfile, Some((std::sync::Arc::new(tempdir.try_clone()?.into()), target_fd)), + opts.progress_to_stdout, ) .await } diff --git a/lib/src/container/update_detachedmeta.rs b/lib/src/container/update_detachedmeta.rs index ddc176d70..50576ed4f 100644 --- a/lib/src/container/update_detachedmeta.rs +++ b/lib/src/container/update_detachedmeta.rs @@ -29,7 +29,7 @@ pub async fn update_detached_metadata( }; // Full copy of the source image - let pulled_digest: String = skopeo::copy(src, &tempsrc_ref, None, None) + let pulled_digest: String = skopeo::copy(src, &tempsrc_ref, None, None, false) .await .context("Creating temporary copy to OCI dir")?; @@ -124,7 +124,7 @@ pub async fn update_detached_metadata( // Finally, copy the mutated image back to the target. For chunked images, // because we only changed one layer, skopeo should know not to re-upload shared blobs. - crate::container::skopeo::copy(&tempsrc_ref, dest, None, None) + crate::container::skopeo::copy(&tempsrc_ref, dest, None, None, false) .await .context("Copying to destination") }