Change behavior of the default arguments in the plugin config (#1063)

## Type of Change
- [x] New feature  
- [x] Breaking change

## Motivation and Context
This PR changes the behavior of the `defaultArguments` field in the
service plugin config. Previously, `defaultArguments` was functioning as
a way to indicate how to start a plugin in the event that the plugin is
loaded at boot (such as for the `container-core-images plugin`).
However, we now follow a convention where all plugins have a "start"
command that is used when launching the plugin, so this
`defaultArguments` field wasn't really providing much. Instead, there
are use cases where we may want to set default values to pass to a
plugin. This PR repurposes the `defaultArguments` field for those use
cases.

As an example use case, there are scenarios where someone may want to
use the AllocationOnlyVmnetNetwork even when running on macOS 26+. This
PR adds the ability to pass in a command line option to the vmnet
network plugin to specify that request. Combined with the
`defaultArguments` plugin config change, a user may choose to set that
field to ["--variant", "allocationOnly"] in the
`container-network-vmnet-config.json` to use AllocationOnlyVmnetNetwork
by default for all networks.

## Testing
- [x] Tested locally
This commit is contained in:
Kathryn Baldauf
2026-01-19 19:22:55 -08:00
committed by GitHub
parent 69445b91b3
commit 9032d73d07
4 changed files with 32 additions and 8 deletions
@@ -79,7 +79,6 @@ public struct PluginConfig: Sendable, Codable {
public let services: [Service]
/// An optional parameter that include any command line arguments
/// that must be passed to the plugin binary when it is loaded.
/// This parameter is used only when `servicesConfig.loadAtBoot` is `true`
public let defaultArguments: [String]
}
+1 -1
View File
@@ -225,7 +225,7 @@ extension PluginLoader {
let plist = LaunchPlist(
label: id,
arguments: [plugin.binaryURL.path] + (args ?? serviceConfig.defaultArguments),
arguments: [plugin.binaryURL.path] + (args ?? ["start"]) + serviceConfig.defaultArguments,
environment: env,
limitLoadToSessionType: [.Aqua, .Background, .System],
runAtLoad: serviceConfig.runAtLoad,
@@ -19,10 +19,16 @@ import ContainerNetworkService
import ContainerNetworkServiceClient
import ContainerResource
import ContainerXPC
import ContainerizationError
import ContainerizationExtras
import Foundation
import Logging
enum Variant: String, ExpressibleByArgument {
case reserved
case allocationOnly
}
extension NetworkVmnetHelper {
struct Start: AsyncParsableCommand {
static let configuration = CommandConfiguration(
@@ -45,6 +51,14 @@ extension NetworkVmnetHelper {
@Option(name: .customLong("subnet-v6"), help: "CIDR address for the IPv6 prefix")
var ipv6Subnet: String?
@Option(name: .long, help: "Variant of the network helper to use.")
var variant: Variant = {
guard #available(macOS 26, *) else {
return .allocationOnly
}
return .reserved
}()
func run() async throws {
let commandName = NetworkVmnetHelper._commandName
let log = setupLogger(id: id, debug: debug)
@@ -63,7 +77,11 @@ extension NetworkVmnetHelper {
ipv4Subnet: ipv4Subnet,
ipv6Subnet: ipv6Subnet,
)
let network = try Self.createNetwork(configuration: configuration, log: log)
let network = try Self.createNetwork(
configuration: configuration,
variant: self.variant,
log: log
)
try await network.start()
let server = try await NetworkService(network: network, log: log)
let xpc = XPCServer(
@@ -86,12 +104,19 @@ extension NetworkVmnetHelper {
}
}
private static func createNetwork(configuration: NetworkConfiguration, log: Logger) throws -> Network {
guard #available(macOS 26, *) else {
private static func createNetwork(configuration: NetworkConfiguration, variant: Variant, log: Logger) throws -> Network {
switch variant {
case .allocationOnly:
return try AllocationOnlyVmnetNetwork(configuration: configuration, log: log)
case .reserved:
guard #available(macOS 26, *) else {
throw ContainerizationError(
.invalidArgument,
message: "variant ReservedVmnetNetwork is only available on macOS 26+"
)
}
return try ReservedVmnetNetwork(configuration: configuration, log: log)
}
return try ReservedVmnetNetwork(configuration: configuration, log: log)
}
}
}
+1 -1
View File
@@ -11,6 +11,6 @@
"description": "Provide an XPC interface to interact with an image store."
}
],
"defaultArguments": ["start"]
"defaultArguments": []
}
}