diff --git a/process/drivers.rs b/process/drivers.rs index e50d3ea..baed928 100644 --- a/process/drivers.rs +++ b/process/drivers.rs @@ -489,11 +489,8 @@ impl ContainerMountDriver for Driver { #[cfg(feature = "rechunk")] impl OciCopy for Driver { - fn copy_oci_dir( - oci_dir: &self::types::OciDir, - registry: &oci_distribution::Reference, - ) -> Result<()> { - SkopeoDriver::copy_oci_dir(oci_dir, registry) + fn copy_oci_dir(opts: &opts::CopyOciDirOpts) -> Result<()> { + SkopeoDriver::copy_oci_dir(opts) } } diff --git a/process/drivers/opts/rechunk.rs b/process/drivers/opts/rechunk.rs index 3269560..d9f59e5 100644 --- a/process/drivers/opts/rechunk.rs +++ b/process/drivers/opts/rechunk.rs @@ -1,8 +1,9 @@ use std::{borrow::Cow, path::Path}; use bon::Builder; +use oci_distribution::Reference; -use crate::drivers::types::{ContainerId, Platform}; +use crate::drivers::types::{ContainerId, OciDir, Platform}; use super::CompressionType; @@ -66,3 +67,12 @@ pub struct VolumeOpts<'scope> { #[builder(default)] pub privileged: bool, } + +#[derive(Debug, Clone, Builder)] +pub struct CopyOciDirOpts<'scope> { + pub oci_dir: &'scope OciDir, + pub registry: &'scope Reference, + + #[builder(default)] + pub privileged: bool, +} diff --git a/process/drivers/skopeo_driver.rs b/process/drivers/skopeo_driver.rs index 667d6f3..c5a88e7 100644 --- a/process/drivers/skopeo_driver.rs +++ b/process/drivers/skopeo_driver.rs @@ -1,5 +1,6 @@ use std::{process::Stdio, time::Duration}; +use blue_build_utils::constants::SUDO_ASKPASS; use cached::proc_macro::cached; use colored::Colorize; use comlexr::cmd; @@ -65,22 +66,45 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result { #[cfg(feature = "rechunk")] impl super::OciCopy for SkopeoDriver { - fn copy_oci_dir( - oci_dir: &super::types::OciDir, - registry: &oci_distribution::Reference, - ) -> Result<()> { + fn copy_oci_dir(opts: &super::opts::CopyOciDirOpts) -> Result<()> { use crate::logging::CommandLogging; + let use_sudo = opts.privileged && !blue_build_utils::running_as_root(); let status = { - let c = cmd!("skopeo", "copy", oci_dir, format!("docker://{registry}"),); + let c = cmd!( + if use_sudo { + "sudo" + } else { + "skopeo" + }, + if use_sudo && blue_build_utils::has_env_var(SUDO_ASKPASS) => [ + "-A", + "-p", + format!( + concat!( + "Password is required to copy ", + "OCI directory {dir:?} to remote registry {registry}" + ), + dir = opts.oci_dir, + registry = opts.registry, + ) + ], + if use_sudo => "skopeo", + "copy", + opts.oci_dir, + format!("docker://{}", opts.registry), + ); trace!("{c:?}"); c } - .build_status(registry.to_string(), format!("Copying {oci_dir} to")) + .build_status( + opts.registry.to_string(), + format!("Copying {} to", opts.oci_dir), + ) .into_diagnostic()?; if !status.success() { - bail!("Failed to copy {oci_dir} to {registry}"); + bail!("Failed to copy {} to {}", opts.oci_dir, opts.registry); } Ok(()) diff --git a/process/drivers/traits.rs b/process/drivers/traits.rs index ecf30d4..01d1876 100644 --- a/process/drivers/traits.rs +++ b/process/drivers/traits.rs @@ -263,10 +263,7 @@ pub(super) trait ContainerMountDriver: PrivateDriver { #[cfg(feature = "rechunk")] pub(super) trait OciCopy { - fn copy_oci_dir( - oci_dir: &super::types::OciDir, - registry: &oci_distribution::Reference, - ) -> Result<()>; + fn copy_oci_dir(opts: &super::opts::CopyOciDirOpts) -> Result<()>; } #[allow(private_bounds)] @@ -341,7 +338,13 @@ pub trait RechunkDriver: RunDriver + BuildDriver + ContainerMountDriver { blue_build_utils::retry(opts.retry_count, 5, || { debug!("Pushing image {tagged_image}"); - Driver::copy_oci_dir(oci_dir, &tagged_image) + Driver::copy_oci_dir( + &super::opts::CopyOciDirOpts::builder() + .oci_dir(oci_dir) + .registry(&tagged_image) + .privileged(true) + .build(), + ) })?; image_list.push(tagged_image.into()); } diff --git a/process/drivers/types.rs b/process/drivers/types.rs index 3a193ad..8a7fb5d 100644 --- a/process/drivers/types.rs +++ b/process/drivers/types.rs @@ -284,12 +284,13 @@ impl<'a> From<&'a MountId> for std::borrow::Cow<'a, str> { } #[cfg(feature = "rechunk")] -pub struct OciDir(String); +#[derive(Debug, Clone)] +pub struct OciDir(std::path::PathBuf); #[cfg(feature = "rechunk")] impl std::fmt::Display for OciDir { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", &self.0) + write!(f, "{}", &self.0.display()) } } @@ -309,6 +310,6 @@ impl TryFrom for OciDir { miette::bail!("OCI directory doesn't exist at {}", value.display()); } - Ok(Self(format!("oci:{}", value.display()))) + Ok(Self(value)) } }