Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,14 @@ async fn get_manifest_layers(
tag: String,
repo: &str,
registry_client: &Client,
) -> Result<(Option<String>, String, Vec<String>), Error> {
) -> Result<(Option<String>, String, Vec<String>, bool), Error> {
trace!("[{}] Fetching release", tag);
let (tag, manifest, manifestref) =
get_manifest_and_ref(tag, repo.to_owned(), &registry_client).await?;

// Check if manifest is a manifest list with a single arch
let is_manifest_list = matches!(&manifest, dkregistry::v2::manifest::Manifest::ML(_));

// Try to read the architecture from the manifest
let arch = match manifest.architectures() {
Ok(archs) => {
Expand Down Expand Up @@ -289,7 +292,7 @@ async fn get_manifest_layers(
.rev()
.collect();

Ok((arch, manifestref, layers_digests))
Ok((arch, manifestref, layers_digests, is_manifest_list))
}

/// Fetches a vector of all release metadata from the given repository, hosted on the given
Expand Down Expand Up @@ -333,7 +336,7 @@ pub async fn fetch_releases(
let misses = cache_misses.clone();

async move {
let (arch, manifestref, mut layers_digests) =
let (arch, manifestref, mut layers_digests, is_manifest_list) =
match get_manifest_layers(tag.to_owned(), &repo, &registry_client).await {
Ok(result) => result,
Err(e) => {
Expand All @@ -357,19 +360,41 @@ pub async fn fetch_releases(
// if the image is multi arch, we will have to get one image from the manifest list and
// use its metadata, because manifest lists are just collections of manifests and don't
// have their own layers with metadata files.
if arch.as_ref().unwrap() == "multi" {
let digest = layers_digests
.first()
.map(std::string::ToString::to_string)
.expect(
format!("no images referenced in ManifestList ref:{}", manifestref)
.as_str(),
);
if is_manifest_list {
let digest = match layers_digests.first() {
Some(d) => d.to_string(),
None => {
error!(
"no images referenced in ManifestList for {}:{} ref:{}",
&repo, &tag, &manifestref
);
skip_releases.fetch_add(1, Ordering::SeqCst);
return Ok(());
}
};
// TODO: destructured assignments are unstable in current rust, after updating rust
// change this to (_,_,layers_digests) and remove separate assignment from below.
let (_ml_arch, _ml_manifestref, ml_layers_digests) =
get_manifest_layers(digest, &repo, &registry_client).await?;
layers_digests = ml_layers_digests;
match get_manifest_layers(digest, &repo, &registry_client).await {
Ok((_ml_arch, _ml_manifestref, ml_layers_digests, _ml_is_manifest_list)) => {
layers_digests = ml_layers_digests;
}
Err(e) => {
if tag.contains(".sig") {
debug!(
"encountered a signature for child manifest {}:{}: {}, ignoring this image",
&repo, &tag, e
);
sig_releases.fetch_add(1, Ordering::SeqCst);
} else {
error!(
"fetching child manifest from ManifestList for {}:{}: {}",
&repo, &tag, e
);
skip_releases.fetch_add(1, Ordering::SeqCst);
}
return Ok(());
}
};
}

let release = match lookup_or_fetch(
Expand Down