mirror of https://github.com/cirruslabs/tart.git
Posibility to add Labels when pushing OCI Image (#1052)
* Posibility to add Labels when pushing OCI Image
Example running:
tart push $image ${registry}/org/${image}-testing --labels com.org.revision=testing --labels com.org.repo.buildid=123456
* Fix Linting
Run swift package plugin --allow-writing-to-package-directory swiftformat --cache ignore
* Update Sources/tart/Commands/Push.swift
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
* Update Sources/tart/Commands/Push.swift
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
* Update Sources/tart/Commands/Push.swift
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
* Update Sources/tart/OCI/Manifest.swift
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
* Update Sources/tart/Commands/Push.swift
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
* Update Sources/tart/Commands/Push.swift
* Do not use a variable to store parseLabels() results
* Trim spaces before splitting labels and support empty values
---------
Co-authored-by: Victor Serbu <victors@4psa.com>
Co-authored-by: Nikolay Edigaryev <edigaryev@gmail.com>
Co-authored-by: Fedor Korotkov <fedor.korotkov@gmail.com>
This commit is contained in:
parent
1560e4d312
commit
df3de33f1a
|
|
@ -26,6 +26,11 @@ struct Push: AsyncParsableCommand {
|
|||
"""))
|
||||
var chunkSize: Int = 0
|
||||
|
||||
|
||||
@Option(name: [.customLong("label")], help: ArgumentHelp("additional metadata to attach to the OCI image configuration in key=value format",
|
||||
discussion: "Can be specified multiple times to attach multiple labels."))
|
||||
var labels: [String] = []
|
||||
|
||||
@Option(help: .hidden)
|
||||
var diskFormat: String = "v2"
|
||||
|
||||
|
|
@ -81,7 +86,8 @@ struct Push: AsyncParsableCommand {
|
|||
references: references,
|
||||
chunkSizeMb: chunkSize,
|
||||
diskFormat: diskFormat,
|
||||
concurrency: concurrency
|
||||
concurrency: concurrency,
|
||||
labels: parseLabels()
|
||||
)
|
||||
// Populate the local cache (if requested)
|
||||
if populateCache {
|
||||
|
|
@ -115,6 +121,28 @@ struct Push: AsyncParsableCommand {
|
|||
return RemoteName(host: registry.host!, namespace: registry.namespace,
|
||||
reference: Reference(digest: digest))
|
||||
}
|
||||
|
||||
// Helper method to convert labels array to dictionary
|
||||
func parseLabels() -> [String: String] {
|
||||
var result = [String: String]()
|
||||
|
||||
for label in labels {
|
||||
let parts = label.trimmingCharacters(in: .whitespaces).split(separator: "=", maxSplits: 1, omittingEmptySubsequences: false)
|
||||
|
||||
let key = parts.count > 0 ? String(parts[0]) : ""
|
||||
let value = parts.count > 1 ? String(parts[1]) : ""
|
||||
|
||||
// It sometimes makes sense to provide an empty value,
|
||||
// but not an empty key
|
||||
if key.isEmpty {
|
||||
continue
|
||||
}
|
||||
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
extension Collection where Element == RemoteName {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,11 @@ struct OCIManifest: Codable, Equatable {
|
|||
struct OCIConfig: Codable {
|
||||
var architecture: Architecture = .arm64
|
||||
var os: OS = .darwin
|
||||
var config: ConfigContainer?
|
||||
|
||||
struct ConfigContainer: Codable {
|
||||
var Labels: [String: String]?
|
||||
}
|
||||
|
||||
func toJSON() throws -> Data {
|
||||
try Config.jsonEncoder().encode(self)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ extension VMDirectory {
|
|||
try manifest.toJSON().write(to: manifestURL)
|
||||
}
|
||||
|
||||
func pushToRegistry(registry: Registry, references: [String], chunkSizeMb: Int, diskFormat: String, concurrency: UInt) async throws -> RemoteName {
|
||||
func pushToRegistry(registry: Registry, references: [String], chunkSizeMb: Int, diskFormat: String, concurrency: UInt, labels: [String: String] = [:]) async throws -> RemoteName {
|
||||
var layers = Array<OCIManifestLayer>()
|
||||
|
||||
// Read VM's config and push it as blob
|
||||
|
|
@ -121,7 +121,8 @@ extension VMDirectory {
|
|||
layers.append(OCIManifestLayer(mediaType: nvramMediaType, size: nvram.count, digest: nvramDigest))
|
||||
|
||||
// Craft a stub OCI config for Docker Hub compatibility
|
||||
let ociConfigJSON = try OCIConfig(architecture: config.arch, os: config.os).toJSON()
|
||||
let ociConfigContainer = OCIConfig.ConfigContainer(Labels: labels)
|
||||
let ociConfigJSON = try OCIConfig(architecture: config.arch, os: config.os, config: ociConfigContainer).toJSON()
|
||||
let ociConfigDigest = try await registry.pushBlob(fromData: ociConfigJSON, chunkSizeMb: chunkSizeMb)
|
||||
let manifest = OCIManifest(
|
||||
config: OCIManifestConfig(size: ociConfigJSON.count, digest: ociConfigDigest),
|
||||
|
|
|
|||
Loading…
Reference in New Issue