diff --git a/Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift b/Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift index 939c42c..64e141d 100644 --- a/Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift +++ b/Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift @@ -15,29 +15,30 @@ extension RegistryClient { /// Get an image configuration record from the registry. /// - Parameters: - /// - repository: Name of the repository containing the record. + /// - image: Reference to the image containing the record. /// - digest: Digest of the record. /// - Returns: The image confguration record stored in `repository` with digest `digest`. /// - Throws: If the blob cannot be decoded as an `ImageConfiguration`. /// /// Image configuration records are stored as blobs in the registry. This function retrieves the requested blob and tries to decode it as a configuration record. - public func getImageConfiguration(repository: String, digest: String) async throws -> ImageConfiguration { - try await getBlob(repository: repository, digest: digest) + public func getImageConfiguration(forImage image: ImageReference, digest: String) async throws -> ImageConfiguration + { + try await getBlob(repository: image.repository, digest: digest) } /// Upload an image configuration record to the registry. /// - Parameters: - /// - repository: Name of the repository in which to store the record. + /// - image: Reference to the image associated with the record. /// - configuration: An image configuration record /// - Returns: An `ContentDescriptor` referring to the blob stored in the registry. /// - Throws: If the blob upload fails. /// /// Image configuration records are stored as blobs in the registry. This function encodes the provided configuration record and stores it as a blob in the registry. - public func putImageConfiguration(repository: String, configuration: ImageConfiguration) async throws + public func putImageConfiguration(forImage image: ImageReference, configuration: ImageConfiguration) async throws -> ContentDescriptor { try await putBlob( - repository: repository, + repository: image.repository, mediaType: "application/vnd.oci.image.config.v1+json", data: configuration ) diff --git a/Sources/containertool/Extensions/RegistryClient+Layers.swift b/Sources/containertool/Extensions/RegistryClient+Layers.swift index d6d344d..ccc79b1 100644 --- a/Sources/containertool/Extensions/RegistryClient+Layers.swift +++ b/Sources/containertool/Extensions/RegistryClient+Layers.swift @@ -16,23 +16,23 @@ import struct Foundation.Data import ContainerRegistry extension RegistryClient { - func getImageManifest(repository: String, reference: String, architecture: String) async throws -> ImageManifest { + func getImageManifest(forImage image: ImageReference, architecture: String) async throws -> ImageManifest { // We pushed the amd64 tag but it points to a single-architecture index, not directly to a manifest // if we get an index we should get a manifest, otherwise we might get a manifest directly do { // Try to retrieve a manifest. If the object with this reference is actually an index, the content-type will not match and // an error will be thrown. - return try await getManifest(repository: repository, reference: reference) + return try await getManifest(repository: image.repository, reference: image.reference) } catch { // Try again, treating the top level object as an index. // This could be more efficient if the exception thrown by getManfiest() included the data it was unable to parse - let index = try await getIndex(repository: repository, reference: reference) + let index = try await getIndex(repository: image.repository, reference: image.reference) guard let manifest = index.manifests.first(where: { $0.platform?.architecture == architecture }) else { throw "Could not find a suitable base image for \(architecture)" } // The index should not point to another index; if it does, this call will throw a final error to be handled by the caller. - return try await getManifest(repository: repository, reference: manifest.digest) + return try await getManifest(repository: image.repository, reference: manifest.digest) } } diff --git a/Sources/containertool/containertool.swift b/Sources/containertool/containertool.swift index db19ea1..d3c873b 100644 --- a/Sources/containertool/containertool.swift +++ b/Sources/containertool/containertool.swift @@ -129,14 +129,13 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti let baseimage_config: ImageConfiguration if let source { baseimage_manifest = try await source.getImageManifest( - repository: baseimage.repository, - reference: baseimage.reference, + forImage: baseimage, architecture: architecture ) log("Found base image manifest: \(baseimage_manifest.digest)") baseimage_config = try await source.getImageConfiguration( - repository: baseimage.repository, + forImage: baseimage, digest: baseimage_manifest.config.digest ) log("Found base image configuration: \(baseimage_manifest.config.digest)") @@ -204,7 +203,7 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti ) let config_blob = try await destination.putImageConfiguration( - repository: destination_image.repository, + forImage: destination_image, configuration: configuration ) diff --git a/Tests/ContainerRegistryTests/SmokeTests.swift b/Tests/ContainerRegistryTests/SmokeTests.swift index 5969d04..d94c7a6 100644 --- a/Tests/ContainerRegistryTests/SmokeTests.swift +++ b/Tests/ContainerRegistryTests/SmokeTests.swift @@ -185,6 +185,7 @@ struct SmokeTests { @Test func testPutAndGetImageConfiguration() async throws { let repository = "testputandgetimageconfiguration" // repository name must be lowercase + let image = ImageReference(registry: "registry", repository: repository, reference: "latest") let configuration = ImageConfiguration( created: "1996-12-19T16:39:57-08:00", @@ -195,12 +196,12 @@ struct SmokeTests { history: [.init(created: "1996-12-19T16:39:57-08:00", author: "test", created_by: "smoketest")] ) let config_descriptor = try await client.putImageConfiguration( - repository: repository, + forImage: image, configuration: configuration ) let downloaded = try await client.getImageConfiguration( - repository: repository, + forImage: image, digest: config_descriptor.digest )