Skip to content
Closed
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
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ define GENERATE_COV_REPORTS
@cat $(COVERAGE_OUTPUT_DIR)/$(2)/coverage-percent.txt
endef

INTEGRATION_TEST_SUITES := \
INTEGRATION_TEST_SUITES ?= \
TestCLIHelp \
TestCLIStatus \
TestCLIVersion \
Expand Down Expand Up @@ -316,7 +316,7 @@ check-licenses:

.PHONY: pre-commit
pre-commit:
cp Scripts/pre-commit.fmt .git/hooks
cp scripts/pre-commit.fmt .git/hooks
touch .git/hooks/pre-commit
cat .git/hooks/pre-commit | grep -v 'hooks/pre-commit\.fmt' > /tmp/pre-commit.new || true
echo 'PRECOMMIT_NOFMT=$${PRECOMMIT_NOFMT} $$(git rev-parse --show-toplevel)/.git/hooks/pre-commit.fmt' >> /tmp/pre-commit.new
Expand Down
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 38 additions & 24 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import PackageDescription
let releaseVersion = ProcessInfo.processInfo.environment["RELEASE_VERSION"] ?? "0.0.0"
let gitCommit = ProcessInfo.processInfo.environment["GIT_COMMIT"] ?? "unspecified"
let builderShimVersion = "0.12.0"
let scVersion = "0.32.2"
let scVersion = "0.33.2"

let package = Package(
name: "container",
Expand All @@ -34,7 +34,9 @@ let package = Package(
.library(name: "ContainerAPIService", targets: ["ContainerAPIService"]),
.library(name: "ContainerAPIClient", targets: ["ContainerAPIClient"]),
.library(name: "ContainerImagesService", targets: ["ContainerImagesService", "ContainerImagesServiceClient"]),
.library(name: "ContainerNetworkService", targets: ["ContainerNetworkService", "ContainerNetworkServiceClient"]),
.library(name: "ContainerNetworkClient", targets: ["ContainerNetworkClient"]),
.library(name: "ContainerNetworkServer", targets: ["ContainerNetworkServer"]),
.library(name: "ContainerNetworkVmnetServer", targets: ["ContainerNetworkVmnetServer"]),
.library(name: "ContainerResource", targets: ["ContainerResource"]),
.library(name: "ContainerLog", targets: ["ContainerLog"]),
.library(name: "ContainerPersistence", targets: ["ContainerPersistence"]),
Expand Down Expand Up @@ -106,7 +108,6 @@ let package = Package(
"ContainerBuild",
"ContainerAPIClient",
"ContainerLog",
"ContainerNetworkService",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
Expand Down Expand Up @@ -166,7 +167,7 @@ let package = Package(
"ContainerAPIService",
"ContainerAPIClient",
"ContainerLog",
"ContainerNetworkService",
"ContainerNetworkClient",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
Expand All @@ -188,7 +189,7 @@ let package = Package(
.product(name: "SystemPackage", package: "swift-system"),
"CVersion",
"ContainerAPIClient",
"ContainerNetworkServiceClient",
"ContainerNetworkClient",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
Expand Down Expand Up @@ -291,13 +292,12 @@ let package = Package(
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationIO", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerLog",
"ContainerNetworkService",
"ContainerNetworkServiceClient",
"ContainerNetworkClient",
"ContainerNetworkServer",
"ContainerNetworkVmnetServer",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
Expand All @@ -308,36 +308,42 @@ let package = Package(
exclude: ["config.toml"]
),
.target(
name: "ContainerNetworkService",
name: "ContainerNetworkClient",
dependencies: [
.product(name: "ContainerizationExtras", package: "containerization"),
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/Network/Client"
),
.target(
name: "ContainerNetworkServer",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerNetworkServiceClient",
"ContainerPersistence",
.product(name: "ContainerizationExtras", package: "containerization"),
"ContainerNetworkClient",
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/ContainerNetworkService/Server"
path: "Sources/Services/Network/Server"
),
.testTarget(
name: "ContainerNetworkServiceTests",
name: "ContainerNetworkServerTests",
dependencies: [
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
"ContainerNetworkService",
"ContainerNetworkServer",
]
),
.target(
name: "ContainerNetworkServiceClient",
name: "ContainerNetworkVmnetServer",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
"ContainerLog",
.product(name: "ContainerizationExtras", package: "containerization"),
"ContainerNetworkServer",
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/ContainerNetworkService/Client"
path: "Sources/Services/NetworkVmnet/Server"
),
.target(
name: "ContainerRuntimeLinuxClient",
Expand Down Expand Up @@ -371,7 +377,7 @@ let package = Package(
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerAPIClient",
"ContainerNetworkServiceClient",
"ContainerNetworkClient",
"ContainerOS",
"ContainerPersistence",
"ContainerResource",
Expand Down Expand Up @@ -520,9 +526,17 @@ let package = Package(
.target(
name: "ContainerVersion",
dependencies: [
"CVersion"
.product(name: "SystemPackage", package: "swift-system"),
"CVersion",
],
),
.testTarget(
name: "ContainerVersionTests",
dependencies: [
.product(name: "SystemPackage", package: "swift-system"),
"ContainerVersion",
]
),
.target(
name: "CVersion",
dependencies: [],
Expand Down
53 changes: 29 additions & 24 deletions Sources/APIServer/APIServer+Start.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import ArgumentParser
import ContainerAPIClient
import ContainerAPIService
import ContainerLog
import ContainerNetworkService
import ContainerPersistence
import ContainerPlugin
import ContainerResource
Expand All @@ -43,16 +42,16 @@ extension APIServer {
@Flag(name: .long, help: "Enable debug logging")
var debug = false

var appRoot = ApplicationRoot.url
var appRoot = ApplicationRoot.path

var installRoot = InstallRoot.url
var installRoot = InstallRoot.path

var logRoot = LogRoot.path

func run() async throws {
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
let commandName = APIServer._commandName
let logPath = logRoot.map { $0.appending("\(commandName).log") }
let logPath = logRoot.map { $0.appending(FilePath.Component("\(commandName).log") ?? "unknown") }
let log = ServiceLogger.bootstrap(category: "APIServer", debug: debug, logPath: logPath)
log.info("starting helper", metadata: ["name": "\(commandName)"])
defer {
Expand Down Expand Up @@ -179,22 +178,24 @@ extension APIServer {
log.info(
"initializing plugin loader",
metadata: [
"installRoot": "\(installRoot.path(percentEncoded: false))"
"installRoot": "\(installRoot.string)"
])

let pluginsURL = PluginLoader.userPluginsDir(installRoot: installRoot)
// TODO: Remove when we convert PluginLoader to FilePath
let installRootURL = URL(fileURLWithPath: installRoot.string)
let pluginsURL = PluginLoader.userPluginsDir(installRoot: installRootURL)
log.info("detecting user plugins directory", metadata: ["path": "\(pluginsURL.path(percentEncoded: false))"])
var directoryExists: ObjCBool = false
_ = FileManager.default.fileExists(atPath: pluginsURL.path, isDirectory: &directoryExists)
let userPluginsURL = directoryExists.boolValue ? pluginsURL : nil

// plugins built into the application installed as a Unix-like application
let installRootPluginsURL =
let installRootPluginsPath =
installRoot
.appendingPathComponent("libexec")
.appendingPathComponent("container")
.appendingPathComponent("plugins")
.standardized
.appending(FilePath.Component("libexec"))
.appending(FilePath.Component("container"))
.appending(FilePath.Component("plugins"))
let installRootPluginsURL = URL(fileURLWithPath: installRootPluginsPath.string)

let pluginDirectories = [
userPluginsURL,
Expand All @@ -210,9 +211,10 @@ extension APIServer {
log.info("discovered plugin directory", metadata: ["path": "\(pluginDirectory.path(percentEncoded: false))"])
}

let appRootURL = URL(fileURLWithPath: appRoot.string)
return try PluginLoader(
appRoot: appRoot,
installRoot: installRoot,
appRoot: appRootURL,
installRoot: installRootURL,
logRoot: logRoot,
pluginDirectories: pluginDirectories,
pluginFactories: pluginFactories,
Expand Down Expand Up @@ -245,9 +247,12 @@ extension APIServer {
private func initializeHealthCheckService(log: Logger, routes: inout [XPCRoute: XPCServer.RouteHandler]) {
log.info("initializing health check service")

// TODO: Remove when we convert HealthCheckHarness to FilePath
let installRootURL = URL(fileURLWithPath: installRoot.string)
let appRootURL = URL(fileURLWithPath: appRoot.string)
let svc = HealthCheckHarness(
appRoot: appRoot,
installRoot: installRoot,
appRoot: appRootURL,
installRoot: installRootURL,
logRoot: logRoot,
log: log
)
Expand All @@ -257,7 +262,9 @@ extension APIServer {
private func initializeKernelService(log: Logger, routes: inout [XPCRoute: XPCServer.RouteHandler]) throws {
log.info("initializing kernel service")

let svc = try KernelService(log: log, appRoot: appRoot)
// TODO: Remove when we convert KernelService to FilePath
let appRootURL = URL(fileURLWithPath: appRoot.string)
let svc = try KernelService(log: log, appRoot: appRootURL)
let harness = KernelHarness(service: svc, log: log)
routes[XPCRoute.installKernel] = XPCServer.route(harness.install)
routes[XPCRoute.getDefaultKernel] = XPCServer.route(harness.getDefaultKernel)
Expand All @@ -271,8 +278,10 @@ extension APIServer {
) throws -> ContainersService {
log.info("initializing containers service")

// TODO: Remove when we convert ContainersService to FilePath
let appRootURL = URL(fileURLWithPath: appRoot.string)
let service = try ContainersService(
appRoot: appRoot,
appRoot: appRootURL,
pluginLoader: pluginLoader,
containerSystemConfig: containerSystemConfig,
log: log,
Expand Down Expand Up @@ -310,9 +319,7 @@ extension APIServer {
) async throws -> NetworksService {
log.info("initializing networks service")

// TODO: This goes away when we convert our roots to FilePath
let appPath = FilePath(appRoot.absolutePath())
let resourceRoot = appPath.appending("networks")
let resourceRoot = appRoot.appending(FilePath.Component("networks"))
let service = try await NetworksService(
pluginLoader: pluginLoader,
resourceRoot: resourceRoot,
Expand All @@ -332,7 +339,7 @@ extension APIServer {
ipv4Subnet: containerSystemConfig.network.subnet,
ipv6Subnet: containerSystemConfig.network.subnetv6,
labels: try .init([ResourceLabelKeys.role: ResourceRoleValues.builtin]),
pluginInfo: NetworkPluginInfo(plugin: "container-network-vmnet")
plugin: "container-network-vmnet"
)
_ = try await service.create(configuration: config)
}
Expand All @@ -355,9 +362,7 @@ extension APIServer {
) throws -> VolumesService {
log.info("initializing volume service")

// TODO: This goes away when we convert our roots to FilePath
let appPath = FilePath(appRoot.absolutePath())
let resourceRoot = appPath.appending("volumes")
let resourceRoot = appRoot.appending(FilePath.Component("volumes"))
let service = try VolumesService(resourceRoot: resourceRoot, containersService: containersService, log: log)
let harness = VolumesHarness(service: service, log: log)

Expand Down
40 changes: 28 additions & 12 deletions Sources/ContainerCommands/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
import ArgumentParser
import ContainerAPIClient
import ContainerLog
import ContainerPersistence
import ContainerPlugin
import ContainerVersion
import ContainerizationError
import ContainerizationOS
import Foundation
import Logging
import SystemPackage
import TerminalProgress

// This logger is only used until `asyncCommand.run()`.
Expand Down Expand Up @@ -136,11 +138,12 @@ public struct Application: AsyncLoggableCommand {
}

public static func createPluginLoader() async throws -> PluginLoader {
let installRoot = CommandLine.executablePathUrl
.deletingLastPathComponent()
.appendingPathComponent("..")
.standardized
let pluginsURL = PluginLoader.userPluginsDir(installRoot: installRoot)
let installRootPath = CommandLine.executablePath
.removingLastComponent()
.removingLastComponent()
// TODO: Remove when we convert PluginLoader to FilePath.
let installRootURL = URL(fileURLWithPath: installRootPath.string)
let pluginsURL = PluginLoader.userPluginsDir(installRoot: installRootURL)
var directoryExists: ObjCBool = false
_ = FileManager.default.fileExists(atPath: pluginsURL.path, isDirectory: &directoryExists)
let userPluginsURL = directoryExists.boolValue ? pluginsURL : nil
Expand All @@ -149,13 +152,12 @@ public struct Application: AsyncLoggableCommand {
let appBundlePluginsURL = Bundle.main.resourceURL?.appending(path: "plugins")

// plugins built into the application installed as a Unix-like application
let installRootPluginsURL =
installRoot
.appendingPathComponent("libexec")
.appendingPathComponent("container")
.appendingPathComponent("plugins")
.standardized

let installRootPluginsPath =
installRootPath
.appending(FilePath.Component("libexec"))
.appending(FilePath.Component("container"))
.appending(FilePath.Component("plugins"))
let installRootPluginsURL = URL(fileURLWithPath: installRootPluginsPath.string)
let pluginDirectories = [
userPluginsURL,
appBundlePluginsURL,
Expand All @@ -180,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.
Expand Down
Loading