Skip to content

Commit ff8a4c6

Browse files
feat: add init-image flag to allow specifying custom init filesystem images per VM
1 parent b671690 commit ff8a4c6

File tree

8 files changed

+32
-11
lines changed

8 files changed

+32
-11
lines changed

Sources/ContainerCommands/Container/ContainerCreate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ extension Application {
8282
)
8383

8484
let options = ContainerCreateOptions(autoRemove: managementFlags.remove)
85-
let container = try await ClientContainer.create(configuration: ck.0, options: options, kernel: ck.1)
85+
let container = try await ClientContainer.create(configuration: ck.0, options: options, kernel: ck.1, initImage: ck.2)
8686

8787
if !self.managementFlags.cidfile.isEmpty {
8888
let path = self.managementFlags.cidfile

Sources/ContainerCommands/Container/ContainerRun.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ extension Application {
111111
let container = try await ClientContainer.create(
112112
configuration: ck.0,
113113
options: options,
114-
kernel: ck.1
114+
kernel: ck.1,
115+
initImage: ck.2
115116
)
116117

117118
let detach = self.managementFlags.detach

Sources/Services/ContainerAPIService/Client/ClientContainer.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ extension ClientContainer {
7878
public static func create(
7979
configuration: ContainerConfiguration,
8080
options: ContainerCreateOptions = .default,
81-
kernel: Kernel
81+
kernel: Kernel,
82+
initImage: String? = nil
8283
) async throws -> ClientContainer {
8384
do {
8485
let client = Self.newXPCClient()
@@ -91,6 +92,10 @@ extension ClientContainer {
9192
request.set(key: .kernel, value: kdata)
9293
request.set(key: .containerOptions, value: odata)
9394

95+
if let initImage {
96+
request.set(key: .initImage, value: initImage)
97+
}
98+
9499
try await xpcSend(client: client, message: request)
95100
return ClientContainer(configuration: configuration)
96101
} catch {

Sources/Services/ContainerAPIService/Client/Flags.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ public struct Flags {
142142
)
143143
public var kernel: String?
144144

145+
@Option(
146+
name: .long,
147+
help: .init("Use a custom init image instead of the default", valueName: "image")
148+
)
149+
public var initImage: String?
150+
145151
@Option(name: [.short, .customLong("label")], help: "Add a key=value label to the container")
146152
public var labels: [String] = []
147153

Sources/Services/ContainerAPIService/Client/Utility.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public struct Utility {
8282
registry: Flags.Registry,
8383
imageFetch: Flags.ImageFetch,
8484
progressUpdate: @escaping ProgressUpdateHandler
85-
) async throws -> (ContainerConfiguration, Kernel) {
85+
) async throws -> (ContainerConfiguration, Kernel, String?) {
8686
var requestedPlatform = Parser.platform(os: management.os, arch: management.arch)
8787
// Prefer --platform
8888
if let platform = management.platform {
@@ -241,7 +241,7 @@ public struct Utility {
241241
config.ssh = management.ssh
242242
config.readOnly = management.readOnly
243243

244-
return (config, kernel)
244+
return (config, kernel, management.initImage)
245245
}
246246

247247
static func getAttachmentConfigurations(containerId: String, networks: [Parser.ParsedNetwork]) throws -> [AttachmentConfiguration] {

Sources/Services/ContainerAPIService/Client/XPC+.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ public enum XPCKeys: String {
106106
case systemPlatform
107107
case kernelForce
108108

109+
/// Init image reference
110+
case initImage
111+
109112
/// Volume
110113
case volume
111114
case volumes

Sources/Services/ContainerAPIService/Server/Containers/ContainersHarness.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,9 @@ public struct ContainersHarness: Sendable {
187187
let config = try JSONDecoder().decode(ContainerConfiguration.self, from: data)
188188
let kernel = try JSONDecoder().decode(Kernel.self, from: kdata)
189189

190-
try await service.create(configuration: config, kernel: kernel, options: options)
190+
let initImage = message.string(key: .initImage)
191+
192+
try await service.create(configuration: config, kernel: kernel, options: options, initImage: initImage)
191193
return message.reply()
192194
}
193195

Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ public actor ContainersService {
192192
}
193193

194194
/// Create a new container from the provided id and configuration.
195-
public func create(configuration: ContainerConfiguration, kernel: Kernel, options: ContainerCreateOptions) async throws {
195+
public func create(configuration: ContainerConfiguration, kernel: Kernel, options: ContainerCreateOptions, initImage: String? = nil) async throws {
196196
self.log.debug("\(#function)")
197197

198198
try await self.lock.withLock { context in
@@ -233,11 +233,14 @@ public actor ContainersService {
233233

234234
let path = self.containerRoot.appendingPathComponent(configuration.id)
235235
let systemPlatform = kernel.platform
236-
let initFs = try await self.getInitBlock(for: systemPlatform.ociPlatform())
236+
237+
// Fetch init image (custom or default)
238+
self.log.info("Using init image: \(initImage ?? ClientImage.initImageRef)")
239+
let initFilesystem = try await self.getInitBlock(for: systemPlatform.ociPlatform(), imageRef: initImage)
237240

238241
let bundle = try ContainerResource.Bundle.create(
239242
path: path,
240-
initialFilesystem: initFs,
243+
initialFilesystem: initFilesystem,
241244
kernel: kernel,
242245
containerConfiguration: configuration
243246
)
@@ -602,8 +605,9 @@ public actor ContainersService {
602605
return options
603606
}
604607

605-
private func getInitBlock(for platform: Platform) async throws -> Filesystem {
606-
let initImage = try await ClientImage.fetch(reference: ClientImage.initImageRef, platform: platform)
608+
private func getInitBlock(for platform: Platform, imageRef: String? = nil) async throws -> Filesystem {
609+
let ref = imageRef ?? ClientImage.initImageRef
610+
let initImage = try await ClientImage.fetch(reference: ref, platform: platform)
607611
var fs = try await initImage.getCreateSnapshot(platform: platform)
608612
fs.options = ["ro"]
609613
return fs

0 commit comments

Comments
 (0)