Support use of custom app root with system config in CLI commands (#1600)

## Type of Change
- [x] Bug fix

## Motivation and Context
Many CLI commands need to reference the system configurations for
`container`. Previously, CLI commands would try to load the system
configurations from the default application root location, regardless of
if `container` had been started with a custom application root location.
This PR fixes that issue by having each CLI command ping the APIServer's
health check service to get the correct app root path.

Closes https://github.com/apple/container/issues/1576

## Testing
- [x] Tested locally

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
This commit is contained in:
Kathryn Baldauf
2026-05-26 14:33:53 -07:00
committed by GitHub
parent ca3a4d6670
commit 25ab5934e4
15 changed files with 29 additions and 14 deletions
@@ -17,6 +17,7 @@
import ArgumentParser
import ContainerAPIClient
import ContainerLog
import ContainerPersistence
import ContainerPlugin
import ContainerVersion
import ContainerizationError
@@ -181,6 +182,20 @@ public struct Application: AsyncLoggableCommand {
)
}
/// Load the system configuration using `appRoot` / `installRoot` reported by the
/// daemon. `container system start` MUST have previously been run to start the daemon.
public static func loadContainerSystemConfig() async throws -> ContainerSystemConfig {
let health = try await ClientHealthCheck.ping(timeout: .seconds(10))
let appRoot = FilePath(health.appRoot.path(percentEncoded: false))
let installRoot = FilePath(health.installRoot.path(percentEncoded: false))
return try await ConfigurationLoader.load(
configurationFiles: [
ConfigurationLoader.configurationFile(in: appRoot, of: .appRoot),
ConfigurationLoader.configurationFile(in: installRoot, of: .installRoot),
]
)
}
public func validate() throws {
// Not really a "validation", but a cheat to run this before
// any of the commands do their business.
+1 -1
View File
@@ -149,7 +149,7 @@ extension Application {
var pull: Bool = false
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
do {
let timeout: Duration = .seconds(300)
let progressConfig = try ProgressConfig(
@@ -55,7 +55,7 @@ extension Application {
public init() {}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let progressConfig = try ProgressConfig(
showTasks: true,
showItems: true,
@@ -56,7 +56,7 @@ extension Application {
var arguments: [String] = []
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let progressConfig = try ProgressConfig(
showTasks: true,
showItems: true,
@@ -63,7 +63,7 @@ extension Application {
var arguments: [String] = []
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
var exitCode: Int32 = 127
let id = Utility.createContainerID(name: self.managementFlags.name)
@@ -109,7 +109,7 @@ extension Application {
}
public mutating func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
try await DeleteImageImplementation.removeImage(options: options, containerSystemConfig: containerSystemConfig, log: log)
}
}
@@ -36,7 +36,7 @@ extension Application {
public init() {}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let uniqueNames = Set(images)
let result = try await ClientImage.get(
names: Array(uniqueNames), containerSystemConfig: containerSystemConfig
@@ -45,7 +45,7 @@ extension Application {
public var logOptions: Flags.Logging
public mutating func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
try Self.validate(quiet: quiet, verbose: verbose)
var images = try await ClientImage.list().filter { img in
@@ -69,7 +69,7 @@ extension Application {
}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let p = try DefaultPlatform.resolve(platform: platform, os: os, arch: arch, log: log)
let scheme = try RequestScheme(registry.scheme)
@@ -57,7 +57,7 @@ extension Application {
public init() {}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let p = try DefaultPlatform.resolve(platform: platform, os: os, arch: arch, log: log)
let scheme = try RequestScheme(registry.scheme)
@@ -67,7 +67,7 @@ extension Application {
@Argument var references: [String]
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let p = try DefaultPlatform.resolve(platform: platform, os: os, arch: arch, log: log)
let progressConfig = try ProgressConfig(
@@ -36,7 +36,7 @@ extension Application {
public var logOptions: Flags.Logging
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let existing = try await ClientImage.get(reference: source, containerSystemConfig: containerSystemConfig)
let targetReference = try ClientImage.normalizeReference(target, containerSystemConfig: containerSystemConfig)
try await existing.tag(new: targetReference)
@@ -47,7 +47,7 @@ extension Application {
var server: String
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
var username = self.username
var password = ""
if passwordStdin {
@@ -53,7 +53,7 @@ extension Application {
public init() {}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
if recommended {
let url = containerSystemConfig.kernel.url
let path: String = containerSystemConfig.kernel.binaryPath
@@ -42,7 +42,7 @@ extension Application {
public init() {}
public func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let containerSystemConfig: ContainerSystemConfig = try await Application.loadContainerSystemConfig()
let output =
switch format {
case .json: try Output.renderJSON(containerSystemConfig)