Skip to content

Commit 3f2309c

Browse files
committed
containertool: manifest and configuration functions should accept ImageReference arguments (#114)
Motivation ---------- `ContainerRegistry` methods follow the distribution API closely. `containertool` defines some extensions which build more convenient operations over these primitive functions. These extensions should accept `ImageReference` arguments. Currently they take separate repository and reference arguments and the caller needs to extract these fields from the appropriate references. This provides an opportunity for errors, such as trying to use the a reference with the wrong repository. Modifications ------------- `getImageManifest()`, `getImageConfiguration()` and `putImageConfiguration()` now accept `ImageReference` arguments. Result ------ The caller no longer has to extract the underlying fields, and the risk of mixing them up is reduced. Test Plan --------- All tests continue to pass.
1 parent fe27bbd commit 3f2309c

File tree

4 files changed

+17
-16
lines changed

4 files changed

+17
-16
lines changed

Sources/ContainerRegistry/RegistryClient+ImageConfiguration.swift

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,30 @@
1515
extension RegistryClient {
1616
/// Get an image configuration record from the registry.
1717
/// - Parameters:
18-
/// - repository: Name of the repository containing the record.
18+
/// - image: Reference to the image containing the record.
1919
/// - digest: Digest of the record.
2020
/// - Returns: The image confguration record stored in `repository` with digest `digest`.
2121
/// - Throws: If the blob cannot be decoded as an `ImageConfiguration`.
2222
///
2323
/// 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.
24-
public func getImageConfiguration(repository: String, digest: String) async throws -> ImageConfiguration {
25-
try await getBlob(repository: repository, digest: digest)
24+
public func getImageConfiguration(forImage image: ImageReference, digest: String) async throws -> ImageConfiguration
25+
{
26+
try await getBlob(repository: image.repository, digest: digest)
2627
}
2728

2829
/// Upload an image configuration record to the registry.
2930
/// - Parameters:
30-
/// - repository: Name of the repository in which to store the record.
31+
/// - image: Reference to the image associated with the record.
3132
/// - configuration: An image configuration record
3233
/// - Returns: An `ContentDescriptor` referring to the blob stored in the registry.
3334
/// - Throws: If the blob upload fails.
3435
///
3536
/// 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.
36-
public func putImageConfiguration(repository: String, configuration: ImageConfiguration) async throws
37+
public func putImageConfiguration(forImage image: ImageReference, configuration: ImageConfiguration) async throws
3738
-> ContentDescriptor
3839
{
3940
try await putBlob(
40-
repository: repository,
41+
repository: image.repository,
4142
mediaType: "application/vnd.oci.image.config.v1+json",
4243
data: configuration
4344
)

Sources/containertool/Extensions/RegistryClient+Layers.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ import struct Foundation.Data
1616
import ContainerRegistry
1717

1818
extension RegistryClient {
19-
func getImageManifest(repository: String, reference: String, architecture: String) async throws -> ImageManifest {
19+
func getImageManifest(forImage image: ImageReference, architecture: String) async throws -> ImageManifest {
2020
// We pushed the amd64 tag but it points to a single-architecture index, not directly to a manifest
2121
// if we get an index we should get a manifest, otherwise we might get a manifest directly
2222

2323
do {
2424
// Try to retrieve a manifest. If the object with this reference is actually an index, the content-type will not match and
2525
// an error will be thrown.
26-
return try await getManifest(repository: repository, reference: reference)
26+
return try await getManifest(repository: image.repository, reference: image.reference)
2727
} catch {
2828
// Try again, treating the top level object as an index.
2929
// This could be more efficient if the exception thrown by getManfiest() included the data it was unable to parse
30-
let index = try await getIndex(repository: repository, reference: reference)
30+
let index = try await getIndex(repository: image.repository, reference: image.reference)
3131
guard let manifest = index.manifests.first(where: { $0.platform?.architecture == architecture }) else {
3232
throw "Could not find a suitable base image for \(architecture)"
3333
}
3434
// The index should not point to another index; if it does, this call will throw a final error to be handled by the caller.
35-
return try await getManifest(repository: repository, reference: manifest.digest)
35+
return try await getManifest(repository: image.repository, reference: manifest.digest)
3636
}
3737
}
3838

Sources/containertool/containertool.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,13 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
129129
let baseimage_config: ImageConfiguration
130130
if let source {
131131
baseimage_manifest = try await source.getImageManifest(
132-
repository: baseimage.repository,
133-
reference: baseimage.reference,
132+
forImage: baseimage,
134133
architecture: architecture
135134
)
136135
log("Found base image manifest: \(baseimage_manifest.digest)")
137136

138137
baseimage_config = try await source.getImageConfiguration(
139-
repository: baseimage.repository,
138+
forImage: baseimage,
140139
digest: baseimage_manifest.config.digest
141140
)
142141
log("Found base image configuration: \(baseimage_manifest.config.digest)")
@@ -204,7 +203,7 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti
204203
)
205204

206205
let config_blob = try await destination.putImageConfiguration(
207-
repository: destination_image.repository,
206+
forImage: destination_image,
208207
configuration: configuration
209208
)
210209

Tests/ContainerRegistryTests/SmokeTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ struct SmokeTests {
185185

186186
@Test func testPutAndGetImageConfiguration() async throws {
187187
let repository = "testputandgetimageconfiguration" // repository name must be lowercase
188+
let image = ImageReference(registry: "registry", repository: repository, reference: "latest")
188189

189190
let configuration = ImageConfiguration(
190191
created: "1996-12-19T16:39:57-08:00",
@@ -195,12 +196,12 @@ struct SmokeTests {
195196
history: [.init(created: "1996-12-19T16:39:57-08:00", author: "test", created_by: "smoketest")]
196197
)
197198
let config_descriptor = try await client.putImageConfiguration(
198-
repository: repository,
199+
forImage: image,
199200
configuration: configuration
200201
)
201202

202203
let downloaded = try await client.getImageConfiguration(
203-
repository: repository,
204+
forImage: image,
204205
digest: config_descriptor.digest
205206
)
206207

0 commit comments

Comments
 (0)