mirror of
https://github.com/apple/container.git
synced 2026-07-16 14:37:07 +00:00
d2f48982c1
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
110 lines
4.3 KiB
Swift
110 lines
4.3 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 Foundation
|
|
|
|
/// Executes ExecOperation (RUN commands).
|
|
public struct ExecOperationExecutor: OperationExecutor {
|
|
public let capabilities: ExecutorCapabilities
|
|
|
|
public init() {
|
|
self.capabilities = ExecutorCapabilities(
|
|
supportedOperations: [.exec],
|
|
maxConcurrency: 5
|
|
)
|
|
}
|
|
|
|
public func execute(_ operation: ContainerBuildIR.Operation, context: ExecutionContext) async throws -> ExecutionResult {
|
|
guard let execOp = operation as? ExecOperation else {
|
|
throw ExecutorError(
|
|
type: .invalidConfiguration,
|
|
context: ExecutorError.ErrorContext(
|
|
operation: operation, underlyingError: NSError(domain: "Executor", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unsupported operation"]),
|
|
diagnostics: ExecutorError.Diagnostics(environment: [:], workingDirectory: "", recentLogs: [])))
|
|
}
|
|
|
|
let startTime = Date()
|
|
|
|
do {
|
|
let (output, finalSnapshot) = try await context.withSnapshot { snapshot in
|
|
try await executeCommand(execOp, in: snapshot, context: context)
|
|
}
|
|
|
|
let duration = Date().timeIntervalSince(startTime)
|
|
|
|
return ExecutionResult(
|
|
environmentChanges: [:], // TODO: Extract environment changes from command execution
|
|
metadataChanges: [:],
|
|
snapshot: finalSnapshot,
|
|
duration: duration,
|
|
output: output
|
|
)
|
|
} catch {
|
|
// Collect diagnostics
|
|
let environment = context.environment.effectiveEnvironment
|
|
let diagnostics = ExecutorError.Diagnostics(
|
|
environment: environment,
|
|
workingDirectory: context.workingDirectory,
|
|
recentLogs: ["Failed to execute: \(execOp.command.displayString)", "Error: \(error.localizedDescription)"]
|
|
)
|
|
|
|
throw ExecutorError(
|
|
type: .executionFailed,
|
|
context: ExecutorError.ErrorContext(
|
|
operation: operation,
|
|
underlyingError: error,
|
|
diagnostics: diagnostics
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Execute a command in the prepared snapshot environment.
|
|
///
|
|
/// This simulates command execution for development and testing purposes.
|
|
/// The snapshotter is fully functional and creates real filesystem snapshots,
|
|
/// but the actual command execution is simulated to avoid system dependencies.
|
|
///
|
|
/// - Parameters:
|
|
/// - operation: The exec operation to perform
|
|
/// - snapshot: The prepared snapshot with working directory
|
|
/// - context: The execution context
|
|
/// - Returns: The simulated execution output
|
|
private func executeCommand(
|
|
_ operation: ExecOperation,
|
|
in snapshot: Snapshot,
|
|
context: ExecutionContext
|
|
) async throws -> ExecutionOutput {
|
|
|
|
let commandString = operation.command.displayString
|
|
|
|
// Simulate command execution
|
|
// The snapshotter will still properly track any filesystem changes
|
|
// that would result from this operation
|
|
return ExecutionOutput(
|
|
stdout: "[SIMULATED] Executing: \(commandString)\nOutput from command execution...\nDone.",
|
|
stderr: "",
|
|
exitCode: 0
|
|
)
|
|
}
|
|
|
|
public func canExecute(_ operation: ContainerBuildIR.Operation) -> Bool {
|
|
operation is ExecOperation
|
|
}
|
|
}
|