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
9
.github/workflows/build-pr.yml
vendored
9
.github/workflows/build-pr.yml
vendored
|
|
@ -124,6 +124,15 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: earthly/actions-setup@v1
|
- uses: earthly/actions-setup@v1
|
||||||
|
|
||||||
|
- name: Earthly login
|
||||||
|
env:
|
||||||
|
EARTHLY_SAT_TOKEN: ${{ secrets.EARTHLY_SAT_TOKEN }}
|
||||||
|
if: env.EARTHLY_SAT_TOKEN != null
|
||||||
|
run: |
|
||||||
|
earthly account login --token ${{ secrets.EARTHLY_SAT_TOKEN }} >> /dev/null
|
||||||
|
earthly org s blue-build
|
||||||
|
earthly sat s pr
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
|
||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -154,7 +154,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
earthly account login --token ${{ secrets.EARTHLY_SAT_TOKEN }} >> /dev/null
|
earthly account login --token ${{ secrets.EARTHLY_SAT_TOKEN }} >> /dev/null
|
||||||
earthly org s blue-build
|
earthly org s blue-build
|
||||||
earthly sat s pr
|
earthly sat s main
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ validate:
|
||||||
FROM +test-base
|
FROM +test-base
|
||||||
|
|
||||||
RUN --no-cache bluebuild -v validate recipes/recipe.yml
|
RUN --no-cache bluebuild -v validate recipes/recipe.yml
|
||||||
RUN --no-cache bluebuild -v validate recipes/recipe-39.yml
|
RUN --no-cache bluebuild -v validate recipes/recipe-gts.yml
|
||||||
RUN --no-cache bluebuild -v validate recipes/recipe-arm64.yml
|
RUN --no-cache bluebuild -v validate recipes/recipe-arm64.yml
|
||||||
RUN --no-cache bluebuild -v validate recipes/recipe-invalid.yml && exit 1 || exit 0
|
RUN --no-cache bluebuild -v validate recipes/recipe-invalid.yml && exit 1 || exit 0
|
||||||
RUN --no-cache bluebuild -v validate recipes/recipe-invalid-module.yml && exit 1 || exit 0
|
RUN --no-cache bluebuild -v validate recipes/recipe-invalid-module.yml && exit 1 || exit 0
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
|
||||||
env,
|
env,
|
||||||
io::Write,
|
io::Write,
|
||||||
path::Path,
|
path::Path,
|
||||||
|
|
@ -21,6 +20,8 @@ use semver::Version;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
mod metadata;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drivers::{
|
drivers::{
|
||||||
opts::{
|
opts::{
|
||||||
|
|
@ -35,37 +36,6 @@ use crate::{
|
||||||
signal_handler::{add_cid, remove_cid, ContainerId, ContainerRuntime},
|
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)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct DockerVerisonJsonClient {
|
struct DockerVerisonJsonClient {
|
||||||
#[serde(alias = "Version")]
|
#[serde(alias = "Version")]
|
||||||
|
|
@ -396,10 +366,10 @@ fn get_metadata_cache(opts: &GetMetadataOpts) -> Result<ImageMetadata> {
|
||||||
bail!("Failed to inspect image {url}")
|
bail!("Failed to inspect image {url}")
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_json::from_slice::<DockerImageMetadata>(&output.stdout)
|
serde_json::from_slice::<metadata::Metadata>(&output.stdout)
|
||||||
.into_diagnostic()
|
.into_diagnostic()
|
||||||
.inspect(|metadata| trace!("{metadata:#?}"))
|
.inspect(|metadata| trace!("{metadata:#?}"))
|
||||||
.map(ImageMetadata::from)
|
.and_then(|metadata| ImageMetadata::try_from((metadata, opts.platform)))
|
||||||
.inspect(|metadata| trace!("{metadata:#?}"))
|
.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 {
|
impl Platform {
|
||||||
/// The architecture of the platform.
|
/// The architecture of the platform.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn arch(&self) -> &str {
|
pub fn arch(&self) -> &str {
|
||||||
match *self {
|
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::LinuxAmd64 => "amd64",
|
||||||
Self::LinuxArm64 => "arm64",
|
Self::LinuxArm64 => "arm64",
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +204,11 @@ impl std::fmt::Display for Platform {
|
||||||
f,
|
f,
|
||||||
"{}",
|
"{}",
|
||||||
match *self {
|
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::LinuxAmd64 => "linux/amd64",
|
||||||
Self::LinuxArm64 => "linux/arm64",
|
Self::LinuxArm64 => "linux/arm64",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue