Optionally resolve wrapper index to single-platform manifest based on com.apple.containerization.index.indirect annotation (#397)

Fixes #212

This PR:
- adds a `package func resolved()` on `ClientImage` that makes use of
the new `com.apple.containerization.index.indirect` annotation to
identify and resolve wrapper indices created by Containerization;
- replace the digest displayed in `container image list` with the one of
the resolved manifest;
- use the resolved manifest for `container image inspect` if the index
is a wrapper.
This commit is contained in:
YR Chen
2025-08-04 11:14:00 -07:00
committed by GitHub
parent 9e9d056339
commit ce431b5c8f
3 changed files with 24 additions and 4 deletions
@@ -69,6 +69,24 @@ public struct ClientImage: Sendable {
}
return try content.decode()
}
/// Returns the resolved OCI descriptor for the image.
package func resolved() async throws -> Descriptor {
let index = try await self.index()
let indirect = index.annotations?[AnnotationKeys.containerizationIndexIndirect]
// If this is not an indirect index, return its own descriptor
guard let indirect, ["1", "true"].contains(indirect.lowercased()) else {
return self.descriptor
}
// For indirect indices, return the first (and only) manifest
guard let manifest = index.manifests.first else {
throw ContainerizationError(
.internalError,
message: "Failed to resolve indirect index \(self.digest): no manifests found"
)
}
return manifest
}
}
// MARK: ClientImage constants
@@ -43,7 +43,7 @@ public struct ImageDetail: Codable {
extension ClientImage {
public func details() async throws -> ImageDetail {
let indexDescriptor = self.descriptor
let descriptor = try await self.resolved()
let reference = self.reference
var variants: [ImageDetail.Variants] = []
for desc in try await self.index().manifests {
@@ -61,6 +61,6 @@ extension ClientImage {
let size = desc.size + manifest.config.size + manifest.layers.reduce(0, { (l, r) in l + r.size })
variants.append(.init(platform: platform, size: size, config: config))
}
return ImageDetail(name: reference, index: indexDescriptor, variants: variants)
return ImageDetail(name: reference, index: descriptor, variants: variants)
}
}