mirror of
https://github.com/apple/container.git
synced 2026-09-12 10:45:42 +00:00
Fix: Allow OCI archives without manifest annotations (#397)
Fixes #369 Per the OCI Image Spec, manifest descriptor annotations are optional. Previously, archives without annotations would fail to import with "Failed to import image". **Changes:** - Modified `getImageReferencefromDescriptor` to return digest-based references (`untagged@sha256:...`) when annotations are missing - Removed guard that skipped manifests without annotations - Added test case with `scratch_no_annotations.tar` **Testing:** All 167 tests pass, including new test for images without annotations.
This commit is contained in:
+4
-1
@@ -90,7 +90,10 @@ let package = Package(
|
||||
name: "ContainerizationUnitTests",
|
||||
dependencies: ["Containerization"],
|
||||
path: "Tests/ContainerizationTests",
|
||||
resources: [.copy("ImageTests/Resources/scratch.tar")]
|
||||
resources: [
|
||||
.copy("ImageTests/Resources/scratch.tar"),
|
||||
.copy("ImageTests/Resources/scratch_no_annotations.tar"),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "ContainerizationEXT4",
|
||||
|
||||
@@ -80,9 +80,7 @@ extension ImageStore {
|
||||
let (id, tempDir) = try await self.contentStore.newIngestSession()
|
||||
do {
|
||||
for descriptor in index.manifests {
|
||||
guard let reference = client.getImageReferencefromDescriptor(descriptor: descriptor) else {
|
||||
continue
|
||||
}
|
||||
let reference = client.getImageReferencefromDescriptor(descriptor: descriptor)
|
||||
let ref = try Reference.parse(reference)
|
||||
let name = ref.path
|
||||
let operation = ImportOperation(name: name, contentStore: self.contentStore, client: client, ingestDir: tempDir, progress: progress)
|
||||
|
||||
@@ -205,11 +205,8 @@ extension LocalOCILayoutClient {
|
||||
descriptor.annotations = annotations
|
||||
}
|
||||
|
||||
package func getImageReferencefromDescriptor(descriptor: Descriptor) -> String? {
|
||||
package func getImageReferencefromDescriptor(descriptor: Descriptor) -> String {
|
||||
let annotations = descriptor.annotations
|
||||
guard let annotations else {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Annotations here do not conform to the OCI image specification.
|
||||
// The interpretation of the annotations "org.opencontainers.image.ref.name" and
|
||||
@@ -220,16 +217,21 @@ extension LocalOCILayoutClient {
|
||||
// https://github.com/moby/buildkit/issues/4615#issuecomment-2521810830
|
||||
// Until a consensus is reached, the preference is given to "com.apple.containerization.image.name" and then to
|
||||
// using "io.containerd.image.name" as it is the next safest choice
|
||||
if let name = annotations[AnnotationKeys.containerizationImageName] {
|
||||
return name
|
||||
if let annotations {
|
||||
if let name = annotations[AnnotationKeys.containerizationImageName] {
|
||||
return name
|
||||
}
|
||||
if let name = annotations[AnnotationKeys.containerdImageName] {
|
||||
return name
|
||||
}
|
||||
if let name = annotations[AnnotationKeys.openContainersImageName] {
|
||||
return name
|
||||
}
|
||||
}
|
||||
if let name = annotations[AnnotationKeys.containerdImageName] {
|
||||
return name
|
||||
}
|
||||
if let name = annotations[AnnotationKeys.openContainersImageName] {
|
||||
return name
|
||||
}
|
||||
return nil
|
||||
|
||||
// Fallback: Generate digest-based reference for images without annotations
|
||||
// This makes sure OCI spec compliance as annotations are optional
|
||||
return "untagged@\(descriptor.digest)"
|
||||
}
|
||||
|
||||
package enum Error: Swift.Error {
|
||||
|
||||
@@ -87,4 +87,26 @@ public class ImageStoreTests: ContainsAuth {
|
||||
let _ = try await self.store.tag(existing: imageReference, new: upstreamTag)
|
||||
try await self.store.push(reference: upstreamTag, auth: authentication)
|
||||
}
|
||||
|
||||
@Test func testLoadImageWithoutAnnotations() async throws {
|
||||
let fileManager = FileManager.default
|
||||
let tempDir = fileManager.uniqueTemporaryDirectory()
|
||||
defer {
|
||||
try? fileManager.removeItem(at: tempDir)
|
||||
}
|
||||
|
||||
let tarPath = Foundation.Bundle.module.url(forResource: "scratch_no_annotations", withExtension: "tar")!
|
||||
let reader = try ArchiveReader(format: .pax, filter: .none, file: tarPath)
|
||||
try reader.extractContents(to: tempDir)
|
||||
|
||||
let loaded = try await self.store.load(from: tempDir)
|
||||
|
||||
#expect(loaded.count == 1)
|
||||
|
||||
let reference = loaded.first!.reference
|
||||
#expect(reference.hasPrefix("untagged@sha256:"))
|
||||
|
||||
let retrieved = try await self.store.get(reference: reference)
|
||||
#expect(retrieved.reference == reference)
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user