fix: Add logic for inspecting multi-manifest images
This commit is contained in:
parent
816a6a5ddd
commit
2b7305c5d0
6 changed files with 105 additions and 39 deletions
|
|
@ -1,5 +1,4 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
io::Write,
|
||||
path::Path,
|
||||
|
|
@ -21,6 +20,8 @@ use semver::Version;
|
|||
use serde::Deserialize;
|
||||
use tempfile::TempDir;
|
||||
|
||||
mod metadata;
|
||||
|
||||
use crate::{
|
||||
drivers::{
|
||||
opts::{
|
||||
|
|
@ -35,37 +36,6 @@ use crate::{
|
|||
signal_handler::{add_cid, remove_cid, ContainerId, ContainerRuntime},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct DockerImageMetadata {
|
||||
manifest: DockerImageMetadataManifest,
|
||||
image: DockerImageMetadataImage,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct DockerImageMetadataManifest {
|
||||
digest: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct DockerImageMetadataImage {
|
||||
config: DockerImageConfig,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
struct DockerImageConfig {
|
||||
labels: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
impl From<DockerImageMetadata> for ImageMetadata {
|
||||
fn from(value: DockerImageMetadata) -> Self {
|
||||
Self {
|
||||
labels: value.image.config.labels,
|
||||
digest: value.manifest.digest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct DockerVerisonJsonClient {
|
||||
#[serde(alias = "Version")]
|
||||
|
|
@ -396,10 +366,10 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
|
|||
bail!("Failed to inspect image {url}")
|
||||
}
|
||||
|
||||
serde_json::from_slice::<DockerImageMetadata>(&output.stdout)
|
||||
serde_json::from_slice::<metadata::Metadata>(&output.stdout)
|
||||
.into_diagnostic()
|
||||
.inspect(|metadata| trace!("{metadata:#?}"))
|
||||
.map(ImageMetadata::from)
|
||||
.and_then(|metadata| ImageMetadata::try_from((metadata, opts.platform)))
|
||||
.inspect(|metadata| trace!("{metadata:#?}"))
|
||||
}
|
||||
|
||||
|
|
|
|||
79
process/drivers/docker_driver/metadata.rs
Normal file
79
process/drivers/docker_driver/metadata.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use miette::{bail, Report};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::drivers::types::{ImageMetadata, Platform};
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct Metadata {
|
||||
manifest: Manifest,
|
||||
image: MetadataImage,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct PlatformManifest {
|
||||
digest: String,
|
||||
platform: PlatformManifestInfo,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct PlatformManifestInfo {
|
||||
architecture: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct Manifest {
|
||||
digest: String,
|
||||
|
||||
#[serde(default)]
|
||||
manifests: Vec<PlatformManifest>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct MetadataPlatformImage {
|
||||
config: Config,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum MetadataImage {
|
||||
Single(MetadataPlatformImage),
|
||||
Multi(HashMap<String, MetadataPlatformImage>),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct Config {
|
||||
labels: HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
impl TryFrom<(Metadata, Platform)> for ImageMetadata {
|
||||
type Error = Report;
|
||||
|
||||
fn try_from((metadata, platform): (Metadata, Platform)) -> Result<Self, Self::Error> {
|
||||
match metadata.image {
|
||||
MetadataImage::Single(image) => Ok(Self {
|
||||
labels: image.config.labels,
|
||||
digest: metadata.manifest.digest,
|
||||
}),
|
||||
MetadataImage::Multi(mut platforms) => {
|
||||
let Some(image) = platforms.remove(&platform.to_string()) else {
|
||||
bail!("Image information does not exist for {platform}");
|
||||
};
|
||||
let Some(manifest) = metadata
|
||||
.manifest
|
||||
.manifests
|
||||
.into_iter()
|
||||
.find(|manifest| manifest.platform.architecture == platform.arch())
|
||||
else {
|
||||
bail!("Manifest does not exist for {platform}");
|
||||
};
|
||||
Ok(Self {
|
||||
labels: image.config.labels,
|
||||
digest: manifest.digest,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,9 +185,13 @@ pub enum Platform {
|
|||
impl Platform {
|
||||
/// The architecture of the platform.
|
||||
#[must_use]
|
||||
pub const fn arch(&self) -> &str {
|
||||
pub fn arch(&self) -> &str {
|
||||
match *self {
|
||||
Self::Native => "native",
|
||||
Self::Native => match std::env::consts::ARCH {
|
||||
"x86_64" => "amd64",
|
||||
"aarch64" => "arm64",
|
||||
arch => unimplemented!("Arch {arch} is unsupported"),
|
||||
},
|
||||
Self::LinuxAmd64 => "amd64",
|
||||
Self::LinuxArm64 => "arm64",
|
||||
}
|
||||
|
|
@ -200,7 +204,11 @@ impl std::fmt::Display for Platform {
|
|||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
Self::Native => "native",
|
||||
Self::Native => match std::env::consts::ARCH {
|
||||
"x86_64" => "linux/amd64",
|
||||
"aarch64" => "linux/arm64",
|
||||
arch => unimplemented!("Arch {arch} is unsupported"),
|
||||
},
|
||||
Self::LinuxAmd64 => "linux/amd64",
|
||||
Self::LinuxArm64 => "linux/arm64",
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue