From b61b932adf1948bdaaf93d370f1d98f1db68d04a Mon Sep 17 00:00:00 2001 From: J Logan Date: Mon, 29 Sep 2025 12:38:45 -0700 Subject: [PATCH] Adds `--add-file` to allow adding files to initfs. (#302) - Motivation is to be able to add the `swift-backtrace-static` binary as needed. - Use singlular `--add-file` and `--label` options since both accept multiple invocations with single values each. Example usage: ```bash ./bin/cctl rootfs create \ --vminitd vminitd/bin/vminitd \ --vmexec vminitd/bin/vmexec \ --add-file /Users/john/.swiftpm/swift-sdks/swift-6.2-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.2-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/aarch64/usr/libexec/swift/linux-static/swift-backtrace-static:sbin/swift-backtrace \ --label org.opencontainers.image.source=https://github.com/apple/containerization \ --image vminit:latest \ bin/init.rootfs.tar.gz ``` --- Makefile | 2 +- Sources/cctl/RootfsCommand.swift | 44 +++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 594c4698..0946776a 100644 --- a/Makefile +++ b/Makefile @@ -62,8 +62,8 @@ init: containerization vminitd @rm -f bin/init.rootfs.tar.gz bin/init.block @./bin/cctl rootfs create \ --vminitd vminitd/bin/vminitd \ - --labels org.opencontainers.image.source=https://github.com/apple/containerization \ --vmexec vminitd/bin/vmexec \ + --label org.opencontainers.image.source=https://github.com/apple/containerization \ --image vminit:latest \ bin/init.rootfs.tar.gz diff --git a/Sources/cctl/RootfsCommand.swift b/Sources/cctl/RootfsCommand.swift index db0a123a..ffb4ed46 100644 --- a/Sources/cctl/RootfsCommand.swift +++ b/Sources/cctl/RootfsCommand.swift @@ -34,23 +34,26 @@ extension Application { ) struct Create: AsyncParsableCommand { - @Option(name: .long, help: "Path to vminitd") - var vminitd: String + @Option(name: [.short, .customLong("add-file")], help: "Additional file to add (format src-path:dst-path)") + var addFiles: [String] = [] - @Option(name: .long, help: "Path to vmexec") - var vmexec: String - - @Option(name: .long, help: "Platform of the built binaries being packaged into the block") - var platformString: String = Platform.current.description - - @Option(name: .long, help: "Labels to add to the built image of the form =, [=,...]") - var labels: [String] = [] + @Option(name: .customLong("ext4"), help: "The path to an ext4 image to create.") + var ext4File: String? @Option(name: .customLong("image"), help: "The name of the image to produce.") var imageName: String? - @Option(name: .customLong("ext4"), help: "The path to an ext4 image to create.") - var ext4File: String? + @Option(name: .customLong("label"), help: "Label to add to the image (format: key=value)") + var labels: [String] = [] + + @Option(name: .long, help: "Platform of the built binaries being packaged into the block") + var platformString: String = Platform.current.description + + @Option(name: .long, help: "Path to vmexec") + var vmexec: String + + @Option(name: .long, help: "Path to vminitd") + var vminitd: String // The path where the intermediate tar archive is created. @Argument var tarPath: String @@ -90,18 +93,17 @@ extension Application { private func outputExt4(archive: URL, to path: URL) async throws { let unpacker = EXT4Unpacker(blockSizeInBytes: 256.mib()) - try unpacker.unpack(archive: archive, compression: .gzip, at: path) } private func outputImage(path: URL, reference: String) async throws { let p = try Platform(from: platformString) - let labels = Application.parseKeyValuePairs(from: labels) + let parsedLabels = Application.parseKeyValuePairs(from: labels) _ = try await InitImage.create( reference: reference, rootfs: path, platform: p, - labels: labels, + labels: parsedLabels, imageStore: Application.imageStore, contentStore: Application.contentStore ) @@ -142,6 +144,18 @@ extension Application { entry.size = Int64(data.count) try writer.writeEntry(entry: entry, data: data) + for addFile in addFiles { + let paths = addFile.components(separatedBy: ":") + guard paths.count == 2 else { + throw ContainerizationError(.invalidArgument, message: "use src-path:dst-path for --add-file") + } + src = URL(fileURLWithPath: paths[0]) + data = try Data(contentsOf: src) + entry.path = paths[1] + entry.size = Int64(data.count) + try writer.writeEntry(entry: entry, data: data) + } + entry.fileType = .symbolicLink entry.path = "proc/self/exe" entry.symlinkTarget = "sbin/vminitd"