fix: Use sudo for skopeo copy for rechunk

This commit is contained in:
Gerald Pinder 2025-03-26 13:02:55 -04:00
parent 7cdb582125
commit 290fbc829b
5 changed files with 56 additions and 21 deletions

View file

@ -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,
}

View file

@ -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<ImageMetadata> {
#[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(())

View file

@ -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());
}

View file

@ -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<std::path::PathBuf> for OciDir {
miette::bail!("OCI directory doesn't exist at {}", value.display());
}
Ok(Self(format!("oci:{}", value.display())))
Ok(Self(value))
}
}