mirror of
https://github.com/apple/container.git
synced 2026-07-12 20:47:04 +00:00
b8965cae43
Closes #339. This change adds named volume support to container, providing volume management CLI commands - `create, delete, list and inspect`. The implementation uses EXT4 block-based persistent storage with a new `VolumesService` actor for thread-safe operations, integrates seamlessly with the existing container mount system through a new `.volume` filesystem type, and provides atomic volume operations with XPC-based API communication. Volumes are stored in isolated directories with configurable sizes (default 512GB) and include proper cleanup and container usage tracking for safe deletion. Example Usage: ``` # Create a volume container volume create mydata # Use volume in container container run -v mydata:/data alpine # List volumes container volume list # Inspect volume details container volume inspect mydata # Clean up container volume rm mydata ```
104 lines
3.6 KiB
Swift
104 lines
3.6 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// 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 Foundation
|
|
|
|
/// A named volume that can be mounted in containers.
|
|
public struct Volume: Sendable, Codable, Equatable, Identifiable {
|
|
// id of the volume.
|
|
public var id: String { name }
|
|
// Name of the volume.
|
|
public var name: String
|
|
// Driver used to create the volume.
|
|
public var driver: String
|
|
// Filesystem format of the volume.
|
|
public var format: String
|
|
// The mount point of the volume on the host.
|
|
public var source: String
|
|
// Timestamp when the volume was created.
|
|
public var createdAt: Date
|
|
// User-defined key/value metadata.
|
|
public var labels: [String: String]
|
|
// Driver-specific options.
|
|
public var options: [String: String]
|
|
// Size of the volume in bytes (optional).
|
|
public var sizeInBytes: UInt64?
|
|
|
|
public init(
|
|
name: String,
|
|
driver: String = "local",
|
|
format: String = "ext4",
|
|
source: String,
|
|
createdAt: Date = Date(),
|
|
labels: [String: String] = [:],
|
|
options: [String: String] = [:],
|
|
sizeInBytes: UInt64? = nil,
|
|
) {
|
|
self.name = name
|
|
self.driver = driver
|
|
self.format = format
|
|
self.source = source
|
|
self.createdAt = createdAt
|
|
self.labels = labels
|
|
self.options = options
|
|
self.sizeInBytes = sizeInBytes
|
|
}
|
|
}
|
|
|
|
/// Error types for volume operations.
|
|
public enum VolumeError: Error, LocalizedError {
|
|
case volumeNotFound(String)
|
|
case volumeAlreadyExists(String)
|
|
case volumeInUse(String)
|
|
case invalidVolumeName(String)
|
|
case driverNotSupported(String)
|
|
case storageError(String)
|
|
|
|
public var errorDescription: String? {
|
|
switch self {
|
|
case .volumeNotFound(let name):
|
|
return "Volume '\(name)' not found"
|
|
case .volumeAlreadyExists(let name):
|
|
return "Volume '\(name)' already exists"
|
|
case .volumeInUse(let name):
|
|
return "Volume '\(name)' is currently in use and cannot be accessed by another container, or deleted."
|
|
case .invalidVolumeName(let name):
|
|
return "Invalid volume name '\(name)'"
|
|
case .driverNotSupported(let driver):
|
|
return "Volume driver '\(driver)' is not supported"
|
|
case .storageError(let message):
|
|
return "Storage error: \(message)"
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Volume storage management utilities.
|
|
public struct VolumeStorage {
|
|
public static let volumeNamePattern = "^[A-Za-z0-9][A-Za-z0-9_.-]*$"
|
|
public static let defaultVolumeSizeBytes: UInt64 = 512 * 1024 * 1024 * 1024 // 512GB
|
|
|
|
public static func isValidVolumeName(_ name: String) -> Bool {
|
|
guard name.count <= 255 else { return false }
|
|
|
|
do {
|
|
let regex = try Regex(volumeNamePattern)
|
|
return name.contains(regex)
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
}
|