Files
container/Sources/NativeBuilder/ContainerBuildExecutor/OperationExecutor.swift
T
Sidhartha Mani d2f48982c1 Native Builder: Define Snapshotter protocol (#491)
This PR defines the snapshotter protocol

```swift
    ///Mount a snapshot and all its previous layers
    func prepare(_ snapshot: Snapshot) async throws -> Snapshot

    /// Commit a snapshot, making it permanent.
    func commit(_ snapshot: Snapshot) async throws -> Snapshot

    /// Remove a snapshot from snapshot store
    func remove(_ snapshot: Snapshot) async throws
```

It updates executors to work with this new protocol
2025-08-12 23:30:56 -07:00

159 lines
5.2 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 ContainerBuildIR
import ContainerBuildSnapshotter
import ContainerizationOCI
import Foundation
/// Executes individual operations within a build.
///
/// Implementations handle the actual execution of operations, interacting with
/// the container runtime, filesystem, and other system resources.
public protocol OperationExecutor: Sendable {
/// The capabilities this executor provides.
var capabilities: ExecutorCapabilities { get }
/// Execute a single operation.
///
/// - Parameters:
/// - operation: The operation to execute
/// - context: The execution context containing current state
/// - Returns: The result of executing the operation
/// - Throws: Any errors encountered during execution
func execute(_ operation: ContainerBuildIR.Operation, context: ExecutionContext) async throws -> ExecutionResult
/// Check if this executor can handle the given operation.
///
/// - Parameter operation: The operation to check
/// - Returns: true if this executor can handle the operation
func canExecute(_ operation: ContainerBuildIR.Operation) -> Bool
}
/// Describes the capabilities of an executor.
///
/// Used by the dispatcher to match operations to appropriate executors.
public struct ExecutorCapabilities: Sendable {
/// The operation kinds this executor can handle.
public let supportedOperations: Set<OperationKind>
/// Platform constraints (nil means all platforms).
public let supportedPlatforms: Set<Platform>?
/// Whether this executor requires privileged access.
public let requiresPrivileged: Bool
/// Maximum concurrent operations this executor can handle.
public let maxConcurrency: Int
/// Resource requirements.
public let resources: ResourceRequirements
public init(
supportedOperations: Set<OperationKind>,
supportedPlatforms: Set<Platform>? = nil,
requiresPrivileged: Bool = false,
maxConcurrency: Int = 10,
resources: ResourceRequirements = .default
) {
self.supportedOperations = supportedOperations
self.supportedPlatforms = supportedPlatforms
self.requiresPrivileged = requiresPrivileged
self.maxConcurrency = maxConcurrency
self.resources = resources
}
}
/// Resource requirements for an executor.
public struct ResourceRequirements: Sendable {
/// Minimum available memory in bytes.
public let minMemory: Int64?
/// Minimum available disk space in bytes.
public let minDiskSpace: Int64?
/// Required CPU architecture.
public let cpuArchitecture: String?
/// Custom requirements.
public let custom: [String: String]
public init(
minMemory: Int64? = nil,
minDiskSpace: Int64? = nil,
cpuArchitecture: String? = nil,
custom: [String: String] = [:]
) {
self.minMemory = minMemory
self.minDiskSpace = minDiskSpace
self.cpuArchitecture = cpuArchitecture
self.custom = custom
}
/// Default resource requirements.
public static let `default` = ResourceRequirements()
}
/// The result of executing an operation.
public struct ExecutionResult: Sendable {
/// Environment changes made by the operation.
public let environmentChanges: [String: EnvironmentValue]
/// Metadata changes (labels, etc.).
public let metadataChanges: [String: String]
/// The snapshot after execution.
public let snapshot: Snapshot
/// Execution duration.
public let duration: TimeInterval
/// Any output produced.
public let output: ExecutionOutput?
public init(
environmentChanges: [String: EnvironmentValue] = [:],
metadataChanges: [String: String] = [:],
snapshot: Snapshot,
duration: TimeInterval,
output: ExecutionOutput? = nil
) {
self.environmentChanges = environmentChanges
self.metadataChanges = metadataChanges
self.snapshot = snapshot
self.duration = duration
self.output = output
}
}
/// Output from operation execution.
public struct ExecutionOutput: Sendable {
/// Standard output.
public let stdout: String
/// Standard error.
public let stderr: String
/// Exit code (for exec operations).
public let exitCode: Int?
public init(stdout: String = "", stderr: String = "", exitCode: Int? = nil) {
self.stdout = stdout
self.stderr = stderr
self.exitCode = exitCode
}
}