From 7bbb5a592a41377f7af81c950b180c870dbc65e5 Mon Sep 17 00:00:00 2001 From: Shawn Wang Date: Thu, 9 May 2024 21:56:42 +0800 Subject: [PATCH] Simple solution to handle ImageIndex --- ocipkg/src/distribution/client.rs | 23 +++++++++++++++++++++-- ocipkg/src/image/artifact.rs | 13 +++++++++++++ ocipkg/src/media_types.rs | 11 +++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/ocipkg/src/distribution/client.rs b/ocipkg/src/distribution/client.rs index a2b2f267..9643f5a7 100644 --- a/ocipkg/src/distribution/client.rs +++ b/ocipkg/src/distribution/client.rs @@ -1,5 +1,5 @@ -use crate::distribution::*; -use anyhow::Result; +use crate::{distribution::*, media_types}; +use anyhow::{bail, Result}; use oci_spec::{distribution::*, image::*}; use url::Url; @@ -106,6 +106,25 @@ impl Client { MediaType::ImageManifest, ), ))?; + + // simple solution to fetch platform manifest from image index + if media_types::is_imageindex(res.content_type()) { + log::debug!("media_type is imageindex type: {}", &res.content_type()); + let mi = ImageIndex::from_reader(res.into_reader())?; + let m = mi.manifests().iter().find(|m| { + m.platform().as_ref().map_or(false, |platform| { + Arch::default().eq(platform.architecture()) + }) + }); + if let Some(m) = m { + return self.get_manifest(&Reference::new(m.digest())?); + } + bail!( + "Found ImageIndex but not supported platform: {}", + Arch::default() + ); + } + let manifest = ImageManifest::from_reader(res.into_reader())?; Ok(manifest) } diff --git a/ocipkg/src/image/artifact.rs b/ocipkg/src/image/artifact.rs index 539e6e30..096f286b 100644 --- a/ocipkg/src/image/artifact.rs +++ b/ocipkg/src/image/artifact.rs @@ -191,6 +191,15 @@ impl Artifact { files.push(path.to_path_buf()); } } + media_type if media_type.to_string().ends_with("gzip") => { + let buf = flate2::read::GzDecoder::new(blob.as_slice()); + let mut ar = tar::Archive::new(buf); + for entry in ar.entries()? { + let entry = entry?; + let path = entry.path()?; + files.push(path.to_path_buf()); + } + } _ => bail!("Unsupported layer type: {}", desc.media_type()), } } @@ -231,6 +240,10 @@ impl Artifact { let buf = flate2::read::GzDecoder::new(blob.as_slice()); tar::Archive::new(buf).unpack(&dest)?; } + (ArtifactVersion::V0, media_type) if media_type.to_string().ends_with("gzip") => { + let buf = flate2::read::GzDecoder::new(blob.as_slice()); + tar::Archive::new(buf).unpack(&dest)?; + } (ArtifactVersion::V1, media_type) if media_type == &media_types::layer_tar_gzip() => { diff --git a/ocipkg/src/media_types.rs b/ocipkg/src/media_types.rs index 34e6176b..943e5ada 100644 --- a/ocipkg/src/media_types.rs +++ b/ocipkg/src/media_types.rs @@ -18,3 +18,14 @@ pub fn config_json() -> MediaType { pub fn layer_tar_gzip() -> MediaType { MediaType::Other("application/vnd.ocipkg.v1.layer.tar+gzip".to_string()) } + +/// Test media_type is imageindex +/// +/// DockerV2S2 can't directly match by MediaType +pub fn is_imageindex(media_type: &str) -> bool { + matches!( + media_type, + "application/vnd.docker.distribution.manifest.list.v2+json" + | "application/vnd.oci.image.index.v1+json" + ) +}