From 384abcd0bd04fdafdb53599dece3c5c7c8f65bd6 Mon Sep 17 00:00:00 2001 From: Nikolay Edigaryev Date: Mon, 27 Jun 2022 16:25:52 +0300 Subject: [PATCH] OCI: make sure annotations are sorted (#138) --- Sources/tart/Config.swift | 12 ++++++++++++ Sources/tart/OCI/Manifest.swift | 19 ++++++++++++++++++- Sources/tart/OCI/Registry.swift | 6 +++--- Sources/tart/VMConfig.swift | 10 +++++++--- Sources/tart/VMDirectory+OCI.swift | 7 +------ Tests/TartTests/RegistryTests.swift | 6 +----- 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Sources/tart/Config.swift b/Sources/tart/Config.swift index 2e73675..6739fec 100644 --- a/Sources/tart/Config.swift +++ b/Sources/tart/Config.swift @@ -6,4 +6,16 @@ struct Config { .appendingPathComponent(".tart", isDirectory: true) public static let tartCacheDir: URL = tartHomeDir.appendingPathComponent("cache", isDirectory: true) + + static func jsonEncoder() -> JSONEncoder { + let encoder = JSONEncoder() + + encoder.outputFormatting = [.sortedKeys] + + return encoder + } + + static func jsonDecoder() -> JSONDecoder { + JSONDecoder() + } } diff --git a/Sources/tart/OCI/Manifest.swift b/Sources/tart/OCI/Manifest.swift index 453704c..6a79e05 100644 --- a/Sources/tart/OCI/Manifest.swift +++ b/Sources/tart/OCI/Manifest.swift @@ -24,8 +24,16 @@ struct OCIManifest: Codable, Equatable { } } + init(fromJSON: Data) throws { + self = try Config.jsonDecoder().decode(Self.self, from: fromJSON) + } + + func toJSON() throws -> Data { + try Config.jsonEncoder().encode(self) + } + func digest() throws -> String { - try Digest.hash(JSONEncoder().encode(self)) + try Digest.hash(toJSON()) } func uncompressedDiskSize() -> UInt64? { @@ -37,6 +45,15 @@ struct OCIManifest: Codable, Equatable { } } +struct OCIConfig: Codable { + var architecture: String = "arm64" + var os: String = "darwin" + + func toJSON() throws -> Data { + try Config.jsonEncoder().encode(self) + } +} + struct OCIManifestConfig: Codable, Equatable { var mediaType: String = ociConfigMediaType var size: Int diff --git a/Sources/tart/OCI/Registry.swift b/Sources/tart/OCI/Registry.swift index 8b088d0..0c975e6 100644 --- a/Sources/tart/OCI/Registry.swift +++ b/Sources/tart/OCI/Registry.swift @@ -34,7 +34,7 @@ struct TokenResponse: Decodable { var issuedAt: Date? static func parse(fromData: Data) throws -> Self { - let decoder = JSONDecoder() + let decoder = Config.jsonDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase @@ -116,7 +116,7 @@ class Registry { } func pushManifest(reference: String, manifest: OCIManifest) async throws -> String { - let manifestJSON = try JSONEncoder().encode(manifest) + let manifestJSON = try manifest.toJSON() let response = try await endpointRequest(.PUT, "\(namespace)/manifests/\(reference)", headers: ["Content-Type": manifest.mediaType], @@ -139,7 +139,7 @@ class Registry { } let manifestData = try await response.body.readResponse() - let manifest = try JSONDecoder().decode(OCIManifest.self, from: manifestData) + let manifest = try OCIManifest(fromJSON: manifestData) return (manifest, manifestData) } diff --git a/Sources/tart/VMConfig.swift b/Sources/tart/VMConfig.swift index a6189e2..c552ede 100644 --- a/Sources/tart/VMConfig.swift +++ b/Sources/tart/VMConfig.swift @@ -59,12 +59,16 @@ struct VMConfig: Codable { memorySize = memorySizeMin } - init(fromData: Data) throws { - self = try JSONDecoder().decode(VMConfig.self, from: fromData) + init(fromJSON: Data) throws { + self = try Config.jsonDecoder().decode(Self.self, from: fromJSON) } init(fromURL: URL) throws { - self = try Self(fromData: try Data(contentsOf: fromURL)) + self = try Self(fromJSON: try Data(contentsOf: fromURL)) + } + + func toJSON() throws -> Data { + try Config.jsonEncoder().encode(self) } func save(toURL: URL) throws { diff --git a/Sources/tart/VMDirectory+OCI.swift b/Sources/tart/VMDirectory+OCI.swift index 4ac5a53..cbaa256 100644 --- a/Sources/tart/VMDirectory+OCI.swift +++ b/Sources/tart/VMDirectory+OCI.swift @@ -139,12 +139,7 @@ extension VMDirectory { layers.append(OCIManifestLayer(mediaType: Self.nvramMediaType, size: nvram.count, digest: nvramDigest)) // Craft a stub OCI config for Docker Hub compatibility - struct OCIConfig: Codable { - var architecture: String = "arm64" - var os: String = "darwin" - } - - let ociConfigJSON = try JSONEncoder().encode(OCIConfig()) + let ociConfigJSON = try OCIConfig().toJSON() let ociConfigDigest = try await registry.pushBlob(fromData: ociConfigJSON) let manifest = OCIManifest( config: OCIManifestConfig(size: ociConfigJSON.count, digest: ociConfigDigest), diff --git a/Tests/TartTests/RegistryTests.swift b/Tests/TartTests/RegistryTests.swift index 2bcd170..3ae757b 100644 --- a/Tests/TartTests/RegistryTests.swift +++ b/Tests/TartTests/RegistryTests.swift @@ -62,11 +62,7 @@ final class RegistryTests: XCTestCase { func testPushPullManifest() async throws { // Craft a basic config - struct OCIConfig: Codable { - var architecture: String = "arm64" - var os: String = "darwin" - } - let configData = try JSONEncoder().encode(OCIConfig()) + let configData = try OCIConfig().toJSON() let configDigest = try await registry.pushBlob(fromData: configData) // Craft a basic layer