Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/ContainerCommands/Builder/BuilderStart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ private func startBuildKit(
)
defer { try? io.close() }

var env: [String: String] = [:]
var dynamicEnv: [String: String] = [:]
if let sshAuthSock = ProcessInfo.processInfo.environment["SSH_AUTH_SOCK"] {
env["SSH_AUTH_SOCK"] = sshAuthSock
dynamicEnv["SSH_AUTH_SOCK"] = sshAuthSock
}

let process = try await client.bootstrap(id: id, stdio: io.stdio, env: env)
let process = try await client.bootstrap(id: id, stdio: io.stdio, dynamicEnv: dynamicEnv)
try await process.start()
await taskManager?.finish()
try io.closeAfterStart()
Expand Down
6 changes: 3 additions & 3 deletions Sources/ContainerCommands/Container/ContainerRun.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,12 @@ extension Application {
try? io.close()
}

var env: [String: String] = [:]
var dynamicEnv: [String: String] = [:]
if let sshAuthSock = ProcessInfo.processInfo.environment["SSH_AUTH_SOCK"] {
env["SSH_AUTH_SOCK"] = sshAuthSock
dynamicEnv["SSH_AUTH_SOCK"] = sshAuthSock
}

let process = try await client.bootstrap(id: id, stdio: io.stdio, env: env)
let process = try await client.bootstrap(id: id, stdio: io.stdio, dynamicEnv: dynamicEnv)
progress.finish()

if !self.managementFlags.cidfile.isEmpty {
Expand Down
2 changes: 1 addition & 1 deletion Sources/ContainerCommands/Container/ContainerStart.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ extension Application {
env["SSH_AUTH_SOCK"] = sshAuthSock
}

let process = try await client.bootstrap(id: container.id, stdio: io.stdio, env: env)
let process = try await client.bootstrap(id: container.id, stdio: io.stdio, dynamicEnv: env)
progress.finish()

if detach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ public struct ContainerClient: Sendable {
}

/// Bootstrap the container's init process.
public func bootstrap(id: String, stdio: [FileHandle?], env: [String: String]? = nil) async throws -> ClientProcess {
public func bootstrap(
id: String,
stdio: [FileHandle?],
dynamicEnv: [String: String] = [:]
) async throws -> ClientProcess {
let request = XPCMessage(route: .containerBootstrap)

for (i, h) in stdio.enumerated() {
Expand All @@ -133,8 +137,8 @@ public struct ContainerClient: Sendable {
}

do {
let env = try JSONEncoder().encode(env)
request.set(key: .env, value: env)
let dynamicEnv = try JSONEncoder().encode(dynamicEnv)
request.set(key: .dynamicEnv, value: dynamicEnv)

request.set(key: .id, value: id)
try await xpcClient.send(request)
Expand Down
4 changes: 2 additions & 2 deletions Sources/Services/ContainerAPIService/Client/XPC+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public enum XPCKeys: String {
case plugin
/// Archive path to export rootfs
case archive
/// Environment variables passed from terminal
case env
/// Special-case environment variables recomputed on each container start
case dynamicEnv

/// Health check request.
case ping
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,10 @@ public struct ContainersHarness: Sendable {
}
let stdio = message.stdio()

guard let data = message.dataNoCopy(key: .env) else {
throw ContainerizationError(
.invalidArgument,
message: "env cannot be empty"
)
}
let env = try JSONDecoder().decode([String: String]?.self, from: data)
let data = message.dataNoCopy(key: .dynamicEnv)
let env = try data.map { try JSONDecoder().decode([String: String].self, from: $0) } ?? [:]

try await service.bootstrap(id: id, stdio: stdio, env: env)
try await service.bootstrap(id: id, stdio: stdio, dynamicEnv: env)
return message.reply()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,13 +398,13 @@ public actor ContainersService {
}

/// Bootstrap the init process of the container.
public func bootstrap(id: String, stdio: [FileHandle?], env: [String: String]?) async throws {
public func bootstrap(id: String, stdio: [FileHandle?], dynamicEnv: [String: String]) async throws {
log.debug(
"ContainersService: enter",
metadata: [
"func": "\(#function)",
"id": "\(id)",
"env": "\(env ?? [:])",
"env": "\(dynamicEnv)",
]
)
defer {
Expand Down Expand Up @@ -474,7 +474,7 @@ public actor ContainersService {
id: id,
runtime: runtime
)
try await sandboxClient.bootstrap(stdio: stdio, allocatedAttachments: allocatedAttachments, env: env)
try await sandboxClient.bootstrap(stdio: stdio, allocatedAttachments: allocatedAttachments, dynamicEnv: dynamicEnv)

try await self.exitMonitor.registerProcess(
id: id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ public struct SandboxClient: Sendable {

// Runtime Methods
extension SandboxClient {
public func bootstrap(stdio: [FileHandle?], allocatedAttachments: [AllocatedAttachment], env: [String: String]? = nil) async throws {
public func bootstrap(
stdio: [FileHandle?],
allocatedAttachments: [AllocatedAttachment],
dynamicEnv: [String: String] = [:]
) async throws {
let request = XPCMessage(route: SandboxRoutes.bootstrap.rawValue)

for (i, h) in stdio.enumerated() {
Expand All @@ -97,8 +101,8 @@ extension SandboxClient {
}

do {
let env = try JSONEncoder().encode(env)
request.set(key: SandboxKeys.env.rawValue, value: env)
let dynamicEnv = try JSONEncoder().encode(dynamicEnv)
request.set(key: SandboxKeys.dynamicEnv.rawValue, value: dynamicEnv)

try request.setAllocatedAttachments(allocatedAttachments)
try await self.client.send(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public enum SandboxKeys: String {
/// Container statistics
case statistics

/// Environment variables passed from terminal.
case env
/// Special-case environment variables recomputed on each container start
case dynamicEnv

/// Network resource keys.
case allocatedAttachments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,16 @@ public actor SandboxService {
}
}

private static func sshAuthSocketHostUrl(config: ContainerConfiguration, hostEnv: [String: String]?, log: Logger? = nil) -> URL? {
private static func sshAuthSocketHostUrl(
config: ContainerConfiguration,
dynamicEnv: [String: String] = [:],
log: Logger? = nil
) -> URL? {
guard config.ssh else {
return nil
}

guard let sshSocket = hostEnv?[Self.sshAuthSocketEnvVar] else {
guard let sshSocket = dynamicEnv[Self.sshAuthSocketEnvVar] else {
log?.warning("ssh forwarding requested but no \(Self.sshAuthSocketEnvVar) found")
return nil
}
Expand Down Expand Up @@ -147,7 +151,7 @@ public actor SandboxService {
)
}

let env = try message.env()
let dynamicEnv = try message.dynamicEnv()

let bundle = ContainerResource.Bundle(path: self.root)
try bundle.createLogFile()
Expand Down Expand Up @@ -224,7 +228,7 @@ public actor SandboxService {
let id = config.id
let rootfs = try bundle.containerRootfs.asMount
let container = try LinuxContainer(id, rootfs: rootfs, vmm: vmm, logger: self.log) { czConfig in
try Self.configureContainer(czConfig: &czConfig, config: config, hostEnv: env, log: self.log)
try Self.configureContainer(czConfig: &czConfig, config: config, dynamicEnv: dynamicEnv, log: self.log)
czConfig.interfaces = interfaces
czConfig.process.stdout = stdout
czConfig.process.stderr = stderr
Expand Down Expand Up @@ -846,7 +850,7 @@ public actor SandboxService {
private static func configureContainer(
czConfig: inout LinuxContainer.Configuration,
config: ContainerConfiguration,
hostEnv: [String: String]?,
dynamicEnv: [String: String] = [:],
log: Logger? = nil,
) throws {
czConfig.cpus = config.resources.cpus
Expand Down Expand Up @@ -880,7 +884,7 @@ public actor SandboxService {
czConfig.sockets.append(socketConfig)
}

if let socketUrl = Self.sshAuthSocketHostUrl(config: config, hostEnv: hostEnv, log: log) {
if let socketUrl = Self.sshAuthSocketHostUrl(config: config, dynamicEnv: dynamicEnv, log: log) {
let socketPath = socketUrl.path(percentEncoded: false)
let attrs = try? FileManager.default.attributesOfItem(atPath: socketPath)
let permissions = (attrs?[.posixPermissions] as? NSNumber)
Expand Down Expand Up @@ -1165,11 +1169,10 @@ extension XPCMessage {
return try JSONDecoder().decode(ProcessConfiguration.self, from: data)
}

fileprivate func env() throws -> [String: String]? {
guard let data = self.dataNoCopy(key: SandboxKeys.env.rawValue) else {
throw ContainerizationError(.invalidArgument, message: "empty env")
}
return try JSONDecoder().decode([String: String]?.self, from: data)
fileprivate func dynamicEnv() throws -> [String: String] {
let data = self.dataNoCopy(key: SandboxKeys.dynamicEnv.rawValue)
let dynamicEnv = try data.map { try JSONDecoder().decode([String: String].self, from: $0) } ?? [:]
return dynamicEnv
}

fileprivate func getAllocatedAttachments() throws -> [AllocatedAttachment] {
Expand Down