//===----------------------------------------------------------------------===// // Copyright © 2025 Apple Inc. and the container project authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //===----------------------------------------------------------------------===// import ArgumentParser import ContainerizationError import Foundation public struct Flags { public struct Global: ParsableArguments { public init() {} @Flag(name: .long, help: "Enable debug output [environment: CONTAINER_DEBUG]") public var debug = false } public struct Process: ParsableArguments { public init() {} @Option( name: [.customLong("cwd"), .customShort("w"), .customLong("workdir")], help: "Current working directory for the container") public var cwd: String? @Option(name: [.customLong("env"), .customShort("e")], help: "Set environment variables") public var env: [String] = [] @Option(name: .customLong("env-file"), help: "Read in a file of environment variables") public var envFile: [String] = [] @Option(name: .customLong("uid"), help: "Set the uid for the process") public var uid: UInt32? @Option(name: .customLong("gid"), help: "Set the gid for the process") public var gid: UInt32? @Flag(name: [.customLong("interactive"), .customShort("i")], help: "Keep Stdin open even if not attached") public var interactive = false @Flag(name: [.customLong("tty"), .customShort("t")], help: "Open a tty with the process") public var tty = false @Option(name: [.customLong("user"), .customShort("u")], help: "Set the user for the process") public var user: String? } public struct Resource: ParsableArguments { public init() {} @Option(name: [.customLong("cpus"), .customShort("c")], help: "Number of CPUs to allocate to the container") public var cpus: Int64? @Option( name: [.customLong("memory"), .customShort("m")], help: "Amount of memory in bytes, kilobytes (K), megabytes (M), or gigabytes (G) for the container, with MB granularity (for example, 1024K will result in 1MB being allocated for the container)" ) public var memory: String? } public struct Registry: ParsableArguments { public init() {} public init(scheme: String) { self.scheme = scheme } @Option(help: "Scheme to use when connecting to the container registry. One of (http, https, auto)") public var scheme: String = "auto" } public struct Management: ParsableArguments { public init() {} @Flag(name: [.customLong("detach"), .short], help: "Run the container and detach from the process") public var detach = false @Option(name: .customLong("entrypoint"), help: "Override the entrypoint of the image") public var entryPoint: String? @Option(name: .customLong("mount"), help: "Add a mount to the container (type=<>,source=<>,target=<>,readonly)") public var mounts: [String] = [] @Option(name: [.customLong("publish"), .short], help: "Publish a port from container to host (format: [host-ip:]host-port:container-port[/protocol])") public var publishPorts: [String] = [] @Option(name: .customLong("publish-socket"), help: "Publish a socket from container to host (format: host_path:container_path)") public var publishSockets: [String] = [] @Option(name: .customLong("tmpfs"), help: "Add a tmpfs mount to the container at the given path") public var tmpFs: [String] = [] @Option(name: .customLong("name"), help: "Assign a name to the container. If excluded will be a generated UUID") public var name: String? @Flag(name: [.customLong("remove"), .customLong("rm")], help: "Remove the container after it stops") public var remove = false @Option(name: .customLong("platform"), help: "Platform for the image if it's multi-platform. This takes precedence over --os and --arch") public var platform: String? @Option(name: .customLong("os"), help: "Set OS if image can target multiple operating systems") public var os = "linux" @Option( name: [.long, .short], help: "Set arch if image can target multiple architectures") public var arch: String = Arch.hostArchitecture().rawValue @Option(name: [.customLong("volume"), .short], help: "Bind mount a volume into the container") public var volumes: [String] = [] @Option( name: [.customLong("kernel"), .short], help: "Set a custom kernel path", completion: .file(), transform: { str in URL(fileURLWithPath: str, relativeTo: .currentDirectory()).absoluteURL.path(percentEncoded: false) }) public var kernel: String? @Option(name: [.customLong("network")], help: "Attach the container to a network") public var networks: [String] = [] @Option(name: .customLong("cidfile"), help: "Write the container ID to the path provided") public var cidfile = "" @Flag(name: [.customLong("no-dns")], help: "Do not configure DNS in the container") public var dnsDisabled = false @Option(name: .customLong("dns"), help: "DNS nameserver IP address") public var dnsNameservers: [String] = [] @Option(name: .customLong("dns-domain"), help: "Default DNS domain") public var dnsDomain: String? = nil @Option(name: .customLong("dns-search"), help: "DNS search domains") public var dnsSearchDomains: [String] = [] @Option(name: .customLong("dns-option"), help: "DNS options") public var dnsOptions: [String] = [] @Option(name: [.customLong("label"), .short], help: "Add a key=value label to the container") public var labels: [String] = [] @Flag( name: [.customLong("virtualization")], help: "Expose virtualization capabilities to the container. (Host must have nested virtualization support, and guest kernel must have virtualization capabilities enabled)" ) public var virtualization: Bool = false @Flag(name: .customLong("ssh"), help: "Forward SSH agent socket to container") public var ssh = false } public struct Progress: ParsableArguments { public init() {} public init(disableProgressUpdates: Bool) { self.disableProgressUpdates = disableProgressUpdates } @Flag(name: .customLong("disable-progress-updates"), help: "Disable progress bar updates") public var disableProgressUpdates = false } }