From f12593c3c2915adc3f2eaa0d9d9c1515b192bb01 Mon Sep 17 00:00:00 2001 From: Aditya Ramani Date: Wed, 4 Jun 2025 09:46:14 -0700 Subject: [PATCH] Register existing runtime plugin launch units on boot (#5) --- .github/workflows/common.yml | 5 +++-- .../Containers/ContainersService.swift | 18 +++++++++++++----- Sources/ContainerBuild/Builder.pb.swift | 8 -------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/common.yml b/.github/workflows/common.yml index f4725569..2055e649 100644 --- a/.github/workflows/common.yml +++ b/.github/workflows/common.yml @@ -30,14 +30,15 @@ jobs: run: | ./scripts/install-hawkeye.sh make fmt - if ! git diff -- . ':(exclude)Package.swift' ':(exclude)Package.resolved'; then echo the following files require formatting or license headers: ; git diff --name-only ; false ; fi + if ! git diff --quiet -- . ':(exclude)Package.swift' ':(exclude)Package.resolved'; then echo "The following files require formatting or license header updates:\n$(git diff --name-only)" ; false ; fi - name: Check protobuf run: | make BUILDER_SHIM_REPO=https://${{ secrets.REPO_READ }}@github.com/apple/container-builder-shim.git protos # TODO [launch]: TEMPORARILY we need to exclude these files since we had to modify them to add # the github token for pulling the private repos. - if ! git diff -- . ':(exclude)Package.swift' ':(exclude)Package.resolved' ':(exclude)Protobuf.Makefile'; then echo the following files require formatting or license headers: ; git diff --name-only ; false ; fi + if ! git diff --quiet -- . ':(exclude)Package.swift' ':(exclude)Package.resolved' ':(exclude)Protobuf.Makefile'; then echo "The following files require formatting or license header updates:\n$(git diff --name-only)" ; false ; fi + env: CURRENT_SDK: y CONTAINERIZATION_REPO: https://${{ secrets.REPO_READ }}@github.com/apple/containerization.git diff --git a/Sources/APIServer/Containers/ContainersService.swift b/Sources/APIServer/Containers/ContainersService.swift index a4692473..6970b9e1 100644 --- a/Sources/APIServer/Containers/ContainersService.swift +++ b/Sources/APIServer/Containers/ContainersService.swift @@ -62,11 +62,11 @@ actor ContainersService { self.containerRoot = containerRoot self.pluginLoader = pluginLoader self.log = log - self.containers = try Self.loadAtBoot(root: containerRoot, log: log) self.runtimePlugins = pluginLoader.findPlugins().filter { $0.hasType(.runtime) } + self.containers = try Self.loadAtBoot(root: containerRoot, loader: pluginLoader, log: log) } - static func loadAtBoot(root: URL, log: Logger) throws -> [String: Item] { + static func loadAtBoot(root: URL, loader: PluginLoader, log: Logger) throws -> [String: Item] { var directories = try FileManager.default.contentsOfDirectory( at: root, includingPropertiesForKeys: [.isDirectoryKey] @@ -75,12 +75,18 @@ actor ContainersService { $0.isDirectory } + let runtimePlugins = loader.findPlugins().filter { $0.hasType(.runtime) } var results = [String: Item]() for dir in directories { do { let bundle = ContainerClient.Bundle(path: dir) let config = try bundle.configuration results[config.id] = .init(bundle: bundle, state: .dead) + let plugin = runtimePlugins.first { $0.name == config.runtimeHandler } + guard let plugin else { + throw ContainerizationError(.internalError, message: "Failed to find runtime plugin \(config.runtimeHandler)") + } + try Self.registerService(plugin: plugin, loader: loader, configuration: config, path: dir) } catch { try? FileManager.default.removeItem(at: dir) log.warning("failed to load container bundle at \(dir.path)") @@ -138,8 +144,9 @@ actor ContainersService { try bundle.setContainerRootFs(cloning: imageFs) try bundle.write(filename: "options.json", value: options) - try self.registerService( + try Self.registerService( plugin: runtimePlugin, + loader: self.pluginLoader, configuration: configuration, path: path ) @@ -161,8 +168,9 @@ actor ContainersService { return fs } - private func registerService( + private static func registerService( plugin: Plugin, + loader: PluginLoader, configuration: ContainerConfiguration, path: URL ) throws { @@ -171,7 +179,7 @@ actor ContainersService { "--uuid", configuration.id, "--debug", ] - try pluginLoader.registerWithLaunchd( + try loader.registerWithLaunchd( plugin: plugin, rootURL: path, args: args, diff --git a/Sources/ContainerBuild/Builder.pb.swift b/Sources/ContainerBuild/Builder.pb.swift index be94f62d..6cb4f5a1 100644 --- a/Sources/ContainerBuild/Builder.pb.swift +++ b/Sources/ContainerBuild/Builder.pb.swift @@ -738,15 +738,11 @@ extension Com_Apple_Container_Build_V1_ClientStream: SwiftProtobuf.Message, Swif var _buildID: String = String() var _packetType: Com_Apple_Container_Build_V1_ClientStream.OneOf_PacketType? - #if swift(>=5.10) // This property is used as the initial default value for new instances of the type. // The type itself is protecting the reference to its storage via CoW semantics. // This will force a copy to be made of this reference when the first mutation occurs; // hence, it is safe to mark this as `nonisolated(unsafe)`. static nonisolated(unsafe) let defaultInstance = _StorageClass() - #else - static let defaultInstance = _StorageClass() - #endif private init() {} @@ -1145,15 +1141,11 @@ extension Com_Apple_Container_Build_V1_ServerStream: SwiftProtobuf.Message, Swif var _buildID: String = String() var _packetType: Com_Apple_Container_Build_V1_ServerStream.OneOf_PacketType? - #if swift(>=5.10) // This property is used as the initial default value for new instances of the type. // The type itself is protecting the reference to its storage via CoW semantics. // This will force a copy to be made of this reference when the first mutation occurs; // hence, it is safe to mark this as `nonisolated(unsafe)`. static nonisolated(unsafe) let defaultInstance = _StorageClass() - #else - static let defaultInstance = _StorageClass() - #endif private init() {}