diff --git a/Plugins/ContainerImageBuilder/main.swift b/Plugins/ContainerImageBuilder/main.swift index f3054c8..434621c 100644 --- a/Plugins/ContainerImageBuilder/main.swift +++ b/Plugins/ContainerImageBuilder/main.swift @@ -99,8 +99,8 @@ extension PluginError: CustomStringConvertible { let helperURL = try context.tool(named: "containertool").url let helperArgs = (FileManager.default.fileExists(atPath: resources.path) ? ["--resources", resources.path] : []) - + extractor.remainingArguments + builtExecutables.map { $0.url.path } + + extractor.remainingArguments let helperEnv = ProcessInfo.processInfo.environment.filter { $0.key.starts(with: "CONTAINERTOOL_") } let err = Pipe() diff --git a/Sources/containertool/Extensions/RegistryClient+publish.swift b/Sources/containertool/Extensions/RegistryClient+publish.swift index 552ee2b..8a6864c 100644 --- a/Sources/containertool/Extensions/RegistryClient+publish.swift +++ b/Sources/containertool/Extensions/RegistryClient+publish.swift @@ -25,6 +25,7 @@ func publishContainerImage( destination: Destination, architecture: String, os: String, + cmd: [String], resources: [String], tag: String?, verbose: Bool, @@ -80,7 +81,7 @@ func publishContainerImage( // and override the entrypoint. var inheritedConfiguration = baseImageConfiguration.config ?? .init() inheritedConfiguration.Entrypoint = ["/\(executableURL.lastPathComponent)"] - inheritedConfiguration.Cmd = [] + inheritedConfiguration.Cmd = cmd inheritedConfiguration.WorkingDir = "/" let configuration = ImageConfiguration( diff --git a/Sources/containertool/containertool.swift b/Sources/containertool/containertool.swift index 46d77ce..779227d 100644 --- a/Sources/containertool/containertool.swift +++ b/Sources/containertool/containertool.swift @@ -64,6 +64,9 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti @Option(help: "Operating system") var os: String? + + @Option(parsing: .remaining, help: "Default arguments to pass to the entrypoint process") + var cmd: [String] = [] } @OptionGroup(title: "Image configuration options") @@ -222,6 +225,7 @@ enum AllowHTTP: String, ExpressibleByArgument, CaseIterable { case source, desti destination: destination, architecture: architecture, os: os, + cmd: imageConfigurationOptions.cmd, resources: imageBuildOptions.resources, tag: repositoryOptions.tag, verbose: verbose, diff --git a/Sources/swift-container-plugin/Documentation.docc/build-container-image.md b/Sources/swift-container-plugin/Documentation.docc/build-container-image.md index 1e4d112..749899c 100644 --- a/Sources/swift-container-plugin/Documentation.docc/build-container-image.md +++ b/Sources/swift-container-plugin/Documentation.docc/build-container-image.md @@ -56,6 +56,10 @@ Wrap a binary in a container image and publish it. - term `--os `: Operating system required to run the image. (default: `linux`) +- term `--cmd …`: + Default arguments to pass to the entrypoint process. + This MUST be the last option present as all following arguments are considered part of the CMD entry. + ### Authentication options - term `--default-username `: diff --git a/scripts/test-containertool-cmd.sh b/scripts/test-containertool-cmd.sh new file mode 100755 index 0000000..a5f882c --- /dev/null +++ b/scripts/test-containertool-cmd.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +##===----------------------------------------------------------------------===## +## +## This source file is part of the SwiftContainerPlugin open source project +## +## Copyright (c) 2025 Apple Inc. and the SwiftContainerPlugin project authors +## Licensed under Apache License v2.0 +## +## See LICENSE.txt for license information +## See CONTRIBUTORS.txt for the list of SwiftContainerPlugin project authors +## +## SPDX-License-Identifier: Apache-2.0 +## +##===----------------------------------------------------------------------===## + +# +# This script assumes that the Static Linux SDK has already been installed +# + +log() { printf -- "** %s\n" "$*" >&2; } +error() { printf -- "** ERROR: %s\n" "$*" >&2; } +fatal() { error "$@"; exit 1; } + +set -euo pipefail + +RUNTIME=${RUNTIME-"docker"} + +# +# Create a test package +# +PKGPATH=$(mktemp -d) +swift package --package-path "$PKGPATH" init --type executable --name hello + +cleanup() { + log "Deleting temporary package $PKGPATH" + rm -rf "$PKGPATH" +} +trap cleanup EXIT + +# +# Build and package an aarch64 binary +# +swift build --package-path "$PKGPATH" --swift-sdk aarch64-swift-linux-musl + +IMGREF=$(swift run containertool --repository localhost:5000/elf_test "$PKGPATH/.build/aarch64-swift-linux-musl/debug/hello" --from scratch --cmd "arg1" "--option" "opt" "--flag") +$RUNTIME pull "$IMGREF" +CMD=$($RUNTIME inspect "$IMGREF" --format "{{.Config.Cmd}}") +if [ "$CMD" = "[arg1 --option opt --flag]" ] ; then + log "cmd option: PASSED" +else + fatal "cmd option: FAILED - cmd was $CMD; expected [arg1 --option opt --flag]" +fi