diff --git a/lib/src/container/store.rs b/lib/src/container/store.rs index 28525f9f..10caa980 100644 --- a/lib/src/container/store.rs +++ b/lib/src/container/store.rs @@ -264,34 +264,36 @@ impl LayeredImageImporter { pub async fn import(self, import: Box) -> Result { let mut proxy = self.proxy; let target_imgref = self.target_imgref.as_ref().unwrap_or(&self.imgref); - let ostree_ref = ref_for_image(&target_imgref.imgref)?; + // First download the base image (if necessary) - we need the SELinux policy // there to label all following layers. let base_layer = import.base_layer; let base_commit = if let Some(c) = base_layer.commit { c } else { - let base_layer_ref = &base_layer.layer; - let (blob, driver) = super::unencapsulate::fetch_layer_decompress( + let base_commit = super::unencapsulate_from_manifest_impl( + &self.repo, &mut proxy, + target_imgref, &self.proxy_img, - &base_layer.layer, + &import.manifest, + None, + true, ) .await?; - let importer = crate::tar::import_tar(&self.repo, blob, None); - let commit = super::unencapsulate::join_fetch(importer, driver) - .await - .with_context(|| format!("Parsing blob {}", base_layer_ref.digest()))?; - // TODO support ref writing in tar import + // Write the ostree ref for that single layer; TODO + // handle this as part of the overall transaction. self.repo.set_ref_immediate( None, base_layer.ostree_ref.as_str(), - Some(commit.as_str()), + Some(base_commit.as_str()), gio::NONE_CANCELLABLE, )?; - commit + base_commit }; + let ostree_ref = ref_for_image(&target_imgref.imgref)?; + let mut layer_commits = Vec::new(); let mut layer_filtered_content: MetaFilteredData = HashMap::new(); for layer in import.layers { diff --git a/lib/src/container/unencapsulate.rs b/lib/src/container/unencapsulate.rs index 880ee522..0f728b7a 100644 --- a/lib/src/container/unencapsulate.rs +++ b/lib/src/container/unencapsulate.rs @@ -181,9 +181,13 @@ pub async fn unencapsulate( options: Option, ) -> Result { let mut proxy = ImageProxy::new().await?; - let (manifest, image_digest) = fetch_manifest_impl(&mut proxy, imgref).await?; + let oi = &proxy.open_image(&imgref.imgref.to_string()).await?; + let (image_digest, raw_manifest) = proxy.fetch_manifest(oi).await?; + let manifest = serde_json::from_slice(&raw_manifest)?; let ostree_commit = - unencapsulate_from_manifest_impl(repo, &mut proxy, imgref, &manifest, options).await?; + unencapsulate_from_manifest_impl(repo, &mut proxy, imgref, oi, &manifest, options, false) + .await?; + proxy.close_image(oi).await?; Ok(Import { ostree_commit, image_digest, @@ -222,12 +226,14 @@ pub(crate) async fn fetch_layer_decompress<'a>( Ok((blob, driver)) } -async fn unencapsulate_from_manifest_impl( +pub(crate) async fn unencapsulate_from_manifest_impl( repo: &ostree::Repo, proxy: &mut ImageProxy, imgref: &OstreeImageReference, + oi: &containers_image_proxy::OpenedImage, manifest: &oci_spec::image::ImageManifest, options: Option, + ignore_layered: bool, ) -> Result { if matches!(imgref.sigverify, SignatureSource::ContainerPolicy) && skopeo::container_policy_is_default_insecure()? @@ -235,15 +241,21 @@ async fn unencapsulate_from_manifest_impl( return Err(anyhow!("containers-policy.json specifies a default of `insecureAcceptAnything`; refusing usage")); } let options = options.unwrap_or_default(); - let layer = require_one_layer_blob(manifest)?; + let layer = if ignore_layered { + manifest + .layers() + .get(0) + .ok_or_else(|| anyhow!("No layers in image"))? + } else { + require_one_layer_blob(manifest)? + }; event!( Level::DEBUG, "target blob digest:{} size: {}", layer.digest().as_str(), layer.size() ); - let oi = proxy.open_image(&imgref.imgref.to_string()).await?; - let (blob, driver) = fetch_layer_decompress(proxy, &oi, layer).await?; + let (blob, driver) = fetch_layer_decompress(proxy, oi, layer).await?; let blob = ProgressReader { reader: blob, progress: options.progress, @@ -272,7 +284,11 @@ pub async fn unencapsulate_from_manifest( options: Option, ) -> Result { let mut proxy = ImageProxy::new().await?; - let r = unencapsulate_from_manifest_impl(repo, &mut proxy, imgref, manifest, options).await?; + let oi = &proxy.open_image(&imgref.imgref.to_string()).await?; + let r = + unencapsulate_from_manifest_impl(repo, &mut proxy, imgref, oi, manifest, options, false) + .await?; + proxy.close_image(oi).await?; // FIXME write ostree commit after proxy finalization proxy.finalize().await?; Ok(r)