From 909ab42ba8130a977186ddea51453241bde3128f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 16 Jan 2024 20:24:05 -0500 Subject: [PATCH] install: Drop support for old skopeo Let's just hard require a skopeo that can fetch from `containers-storage`. Motivated by https://github.com/containers/bootc/pull/263 which was moving this code around. Signed-off-by: Colin Walters --- lib/src/install.rs | 106 +++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 76 deletions(-) diff --git a/lib/src/install.rs b/lib/src/install.rs index 3a26db230..0c343dbb5 100644 --- a/lib/src/install.rs +++ b/lib/src/install.rs @@ -245,14 +245,7 @@ pub(crate) struct SourceInfo { /// Whether or not SELinux appears to be enabled in the source commit pub(crate) selinux: bool, /// Whether the source is available in the host mount namespace - pub(crate) in_host_mountns: Option, -} - -/// Information about the host mount namespace -#[derive(Debug, Clone)] -pub(crate) struct HostMountnsInfo { - /// True if the skoepo on host supports containers-storage: - pub(crate) skopeo_supports_containers_storage: bool, + pub(crate) in_host_mountns: bool, } // Shared read-only global state @@ -397,25 +390,22 @@ impl SourceInfo { let skopeo_supports_containers_storage = skopeo_supports_containers_storage() .context("Failed to run skopeo (it currently must be installed in the host root)")?; - Self::from( - imageref, - Some(digest), - Some(HostMountnsInfo { - skopeo_supports_containers_storage, - }), - ) + if !skopeo_supports_containers_storage { + anyhow::bail!("This functionality requires at least skopeo v1.11 on the host"); + } + Self::from(imageref, Some(digest), true) } #[context("Creating source info from a given imageref")] pub(crate) fn from_imageref(imageref: &str) -> Result { let imageref = ostree_container::ImageReference::try_from(imageref)?; - Self::from(imageref, None, None) + Self::from(imageref, None, false) } fn from( imageref: ostree_container::ImageReference, digest: Option, - in_host_mountns: Option, + in_host_mountns: bool, ) -> Result { let cancellable = ostree::gio::Cancellable::NONE; let commit = Task::new("Reading ostree commit", "ostree") @@ -612,39 +602,31 @@ async fn initialize_ostree_root_from_self( let sysroot = ostree::Sysroot::new(Some(&gio::File::for_path(rootfs))); sysroot.load(cancellable)?; - let mut temporary_dir = None; - let (src_imageref, proxy_cfg) = match &state.source.in_host_mountns { - None => (state.source.imageref.clone(), None), - Some(host_mountns_info) => { - let src_imageref = if host_mountns_info.skopeo_supports_containers_storage { - // We always use exactly the digest of the running image to ensure predictability. - let digest = state - .source - .digest - .as_ref() - .ok_or_else(|| anyhow::anyhow!("Missing container image digest"))?; - let spec = crate::utils::digested_pullspec(&state.source.imageref.name, digest); - ostree_container::ImageReference { - transport: ostree_container::Transport::ContainerStorage, - name: spec, - } - } else { - let td = tempfile::tempdir_in("/var/tmp")?; - let path: &Utf8Path = td.path().try_into().unwrap(); - let r = copy_to_oci(&state.source.imageref, path)?; - temporary_dir = Some(td); - r - }; + let (src_imageref, proxy_cfg) = if !state.source.in_host_mountns { + (state.source.imageref.clone(), None) + } else { + let src_imageref = { + // We always use exactly the digest of the running image to ensure predictability. + let digest = state + .source + .digest + .as_ref() + .ok_or_else(|| anyhow::anyhow!("Missing container image digest"))?; + let spec = crate::utils::digested_pullspec(&state.source.imageref.name, digest); + ostree_container::ImageReference { + transport: ostree_container::Transport::ContainerStorage, + name: spec, + } + }; - // We need to fetch the container image from the root mount namespace - let skopeo_cmd = run_in_host_mountns("skopeo"); - let proxy_cfg = ostree_container::store::ImageProxyConfig { - skopeo_cmd: Some(skopeo_cmd), - ..Default::default() - }; + // We need to fetch the container image from the root mount namespace + let skopeo_cmd = run_in_host_mountns("skopeo"); + let proxy_cfg = ostree_container::store::ImageProxyConfig { + skopeo_cmd: Some(skopeo_cmd), + ..Default::default() + }; - (src_imageref, Some(proxy_cfg)) - } + (src_imageref, Some(proxy_cfg)) }; let src_imageref = ostree_container::OstreeImageReference { // There are no signatures to verify since we're fetching the already @@ -671,8 +653,6 @@ async fn initialize_ostree_root_from_self( println!("Installed: {target_image}"); println!(" Digest: {digest}"); - drop(temporary_dir); - // Write the entry for /boot to /etc/fstab. TODO: Encourage OSes to use the karg? // Or better bind this with the grub data. sysroot.load(cancellable)?; @@ -717,32 +697,6 @@ async fn initialize_ostree_root_from_self( Ok(aleph) } -#[context("Copying to oci")] -fn copy_to_oci( - src_imageref: &ostree_container::ImageReference, - dir: &Utf8Path, -) -> Result { - tracing::debug!("Copying {src_imageref}"); - let src_imageref = src_imageref.to_string(); - let dest_imageref = ostree_container::ImageReference { - transport: ostree_container::Transport::OciDir, - name: dir.to_string(), - }; - let dest_imageref_str = dest_imageref.to_string(); - Task::new_cmd( - "Copying to temporary OCI (skopeo is too old)", - run_in_host_mountns("skopeo"), - ) - .args([ - "copy", - // TODO: enable this once ostree is fixed "--dest-oci-accept-uncompressed-layers", - src_imageref.as_str(), - dest_imageref_str.as_str(), - ]) - .run()?; - Ok(dest_imageref) -} - /// Run a command in the host mount namespace pub(crate) fn run_in_host_mountns(cmd: &str) -> Command { let mut c = Command::new("/proc/self/exe");