From eddd6ea4afcbc40f43cea1e821e8c47b85a72793 Mon Sep 17 00:00:00 2001 From: shoce Date: Thu, 17 Sep 2026 18:25:31 +0700 Subject: [PATCH] K8s plugin: Add --volume and --mount options support --- Sources/ContainerK8s/Commands/K8sCreate.swift | 10 +++++++++- .../Provisioners/LinuxNodeProvisioner.swift | 12 +++++++++--- docs/command-reference.md | 13 ++++++++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Sources/ContainerK8s/Commands/K8sCreate.swift b/Sources/ContainerK8s/Commands/K8sCreate.swift index 3432240e1..c8a6c9d8e 100644 --- a/Sources/ContainerK8s/Commands/K8sCreate.swift +++ b/Sources/ContainerK8s/Commands/K8sCreate.swift @@ -54,6 +54,12 @@ public struct K8sCreate: AsyncParsableCommand { @Option(name: .long, help: "Optional path to a CNI manifest to apply.") var cni: String? + @Option(name: [.customLong("volume"), .short], help: "Bind mount a volume into the cluster node (format: [source:]destination[:options])") + var volumes: [String] = [] + + @Option(name: .customLong("mount"), help: "Add a mount to the cluster node (format: type=<>,source=<>,target=<>,readonly)") + var mounts: [String] = [] + public func run() async throws { LoggingSystem.bootstrap { _ in StderrLogHandler() } let log = Logger(label: K8sHelper.pluginName) @@ -95,7 +101,9 @@ public struct K8sCreate: AsyncParsableCommand { registryScheme: registryFlags.scheme, maxConcurrentDownloads: imageFetchFlags.maxConcurrentDownloads, remove: remove, - fqdn: fqdn + fqdn: fqdn, + volumes: volumes, + mounts: mounts ) progress.set(description: "Starting cluster") diff --git a/Sources/ContainerK8s/Provisioners/LinuxNodeProvisioner.swift b/Sources/ContainerK8s/Provisioners/LinuxNodeProvisioner.swift index c50f7d02b..3d37eb42f 100644 --- a/Sources/ContainerK8s/Provisioners/LinuxNodeProvisioner.swift +++ b/Sources/ContainerK8s/Provisioners/LinuxNodeProvisioner.swift @@ -32,6 +32,8 @@ public struct LinuxNodeProvisioner: NodeProvisioner { private let maxConcurrentDownloads: Int private let remove: Bool private let fqdn: String? + private let volumes: [String] + private let mounts: [String] public init( clusterName: String, @@ -42,7 +44,9 @@ public struct LinuxNodeProvisioner: NodeProvisioner { registryScheme: String = "https", maxConcurrentDownloads: Int = 3, remove: Bool = false, - fqdn: String? = nil + fqdn: String? = nil, + volumes: [String] = [], + mounts: [String] = [] ) throws { guard !roles.isEmpty else { throw ContainerizationError(.invalidArgument, message: "LinuxNode roles must not be empty") @@ -63,6 +67,8 @@ public struct LinuxNodeProvisioner: NodeProvisioner { self.maxConcurrentDownloads = maxConcurrentDownloads self.remove = remove self.fqdn = fqdn + self.volumes = volumes + self.mounts = mounts } public func provision(name: String, log: Logger) async throws { @@ -90,7 +96,7 @@ public struct LinuxNodeProvisioner: NodeProvisioner { "\(ResourceLabelKeys.role)=\(roles.joined(separator: ","))", ], maskedPaths: [], - mounts: [], + mounts: mounts, name: name, networks: [], os: "linux", @@ -107,7 +113,7 @@ public struct LinuxNodeProvisioner: NodeProvisioner { tmpFs: [], useInit: false, virtualization: false, - volumes: [] + volumes: volumes ) let updatedResource = K8sHelper.defaultedResourceFlags(Flags.Resource(cpus: cpus, memory: memory)) diff --git a/docs/command-reference.md b/docs/command-reference.md index 9361036aa..7a64845dd 100644 --- a/docs/command-reference.md +++ b/docs/command-reference.md @@ -1610,7 +1610,7 @@ Creates and starts a local Kubernetes cluster. Pulls the node image if needed, r **Usage** ```bash -container k8s create [--name ] [--node-image ] [--cni ] [--rm] [] [--debug] +container k8s create [--name ] [--node-image ] [--cni ] [--rm] [--volume ] [--mount ] [] [--debug] ``` **Options** @@ -1619,6 +1619,8 @@ container k8s create [--name ] [--node-image ] [--cni ] [--rm * `--node-image `: Node image reference (default: `docker.io/kindest/node:v1.35.5`) * `--cni `: Optional path to a CNI manifest to apply. If not provided, the bundled kindnet CNI is used. * `--rm`: Remove the cluster container after it stops +* `--volume, -v `: Bind mount a host directory or named volume into the cluster node (format: `[source:]destination[:options]`, repeatable). Uses the same syntax as `container run --volume`. +* `--mount `: Add a mount to the cluster node (format: `type=<>,source=<>,target=<>,readonly`, repeatable). Uses the same syntax as `container run --mount`. **Resource Options** @@ -1647,6 +1649,15 @@ container k8s create --name temp-cluster --rm # create a cluster using a custom CNI manifest instead of the bundled kindnet container k8s create --cni ./my-cni.yaml + +# create a cluster with a host directory bind-mounted into the node +container k8s create --volume /Users/me/data:/mnt/data + +# create a cluster with a named, managed volume mounted read-only +container k8s create --volume mydata:/mnt/data:ro + +# create a cluster with an explicit mount using type=/source=/target= syntax +container k8s create --mount type=bind,source=/Users/me/data,target=/mnt/data,readonly ``` ### `container k8s start`