mirror of
https://github.com/trycua/computer.git
synced 2026-01-05 21:09:58 -06:00
Merge pull request #67 from aktech/add-no-cache-option-pull-image
Add `--no-cache` option in lume pull
This commit is contained in:
@@ -151,7 +151,8 @@ curl --connect-timeout 6000 \
|
||||
"image": "macos-sequoia-vanilla:latest",
|
||||
"name": "my-vm-name",
|
||||
"registry": "ghcr.io",
|
||||
"organization": "trycua"
|
||||
"organization": "trycua",
|
||||
"noCache": false
|
||||
}' \
|
||||
http://localhost:3000/lume/pull
|
||||
```
|
||||
|
||||
@@ -17,12 +17,15 @@ struct Pull: AsyncParsableCommand {
|
||||
|
||||
@Option(help: "Organization to pull from. Defaults to trycua")
|
||||
var organization: String = "trycua"
|
||||
|
||||
|
||||
@Flag(help: "Pull image without creating .cache. Defaults to false")
|
||||
var noCache: Bool = false
|
||||
|
||||
init() {}
|
||||
|
||||
@MainActor
|
||||
func run() async throws {
|
||||
let vmController = LumeController()
|
||||
try await vmController.pullImage(image: image, name: name, registry: registry, organization: organization)
|
||||
try await vmController.pullImage(image: image, name: name, registry: registry, organization: organization, noCache: noCache)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ class ImageContainerRegistry: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
func pull(image: String, name: String?) async throws {
|
||||
func pull(image: String, name: String?, noCache: Bool = false) async throws {
|
||||
// Validate home directory
|
||||
let home = Home()
|
||||
try home.validateHomeDirectory()
|
||||
@@ -287,27 +287,32 @@ class ImageContainerRegistry: @unchecked Sendable {
|
||||
try? FileManager.default.removeItem(at: tempVMDir)
|
||||
}
|
||||
|
||||
// Check if we have a valid cached version
|
||||
// Check if we have a valid cached version and noCache is false
|
||||
Logger.info("Checking cache for manifest ID: \(manifestId)")
|
||||
if validateCache(manifest: manifest, manifestId: manifestId) {
|
||||
if !noCache && validateCache(manifest: manifest, manifestId: manifestId) {
|
||||
Logger.info("Using cached version of image")
|
||||
try await copyFromCache(manifest: manifest, manifestId: manifestId, to: tempVMDir)
|
||||
} else {
|
||||
// Clean up old versions of this repository before setting up new cache
|
||||
try cleanupOldVersions(currentManifestId: manifestId, image: imageName)
|
||||
if !noCache {
|
||||
try cleanupOldVersions(currentManifestId: manifestId, image: imageName)
|
||||
}
|
||||
|
||||
Logger.info("Cache miss or invalid cache, setting up new cache")
|
||||
// Setup new cache directory
|
||||
try setupImageCache(manifestId: manifestId)
|
||||
if noCache {
|
||||
Logger.info("Skipping cache setup due to noCache option")
|
||||
} else {
|
||||
Logger.info("Cache miss or invalid cache, setting up new cache")
|
||||
// Setup new cache directory
|
||||
try setupImageCache(manifestId: manifestId)
|
||||
// Save new manifest
|
||||
try saveManifest(manifest, manifestId: manifestId)
|
||||
|
||||
// Save new manifest
|
||||
try saveManifest(manifest, manifestId: manifestId)
|
||||
|
||||
// Save image metadata
|
||||
try saveImageMetadata(
|
||||
image: imageName,
|
||||
manifestId: manifestId
|
||||
)
|
||||
// Save image metadata
|
||||
try saveImageMetadata(
|
||||
image: imageName,
|
||||
manifestId: manifestId
|
||||
)
|
||||
}
|
||||
|
||||
// Create temporary directory for new downloads
|
||||
let tempDownloadDir = FileManager.default.temporaryDirectory.appendingPathComponent(
|
||||
@@ -375,12 +380,12 @@ class ImageContainerRegistry: @unchecked Sendable {
|
||||
let cachedLayer = getCachedLayerPath(
|
||||
manifestId: manifestId, digest: layer.digest)
|
||||
|
||||
if FileManager.default.fileExists(atPath: cachedLayer.path) {
|
||||
if !noCache && FileManager.default.fileExists(atPath: cachedLayer.path) {
|
||||
try FileManager.default.copyItem(at: cachedLayer, to: outputURL)
|
||||
await progress.addProgress(Int64(layer.size))
|
||||
} else {
|
||||
// Check if this layer is already being downloaded
|
||||
if isDownloading(layer.digest) {
|
||||
// Check if this layer is already being downloaded and we're not skipping cache
|
||||
if !noCache && isDownloading(layer.digest) {
|
||||
try await waitForExistingDownload(
|
||||
layer.digest, cachedLayer: cachedLayer)
|
||||
if FileManager.default.fileExists(atPath: cachedLayer.path) {
|
||||
@@ -391,8 +396,9 @@ class ImageContainerRegistry: @unchecked Sendable {
|
||||
}
|
||||
|
||||
// Start new download
|
||||
markDownloadStarted(layer.digest)
|
||||
defer { markDownloadComplete(layer.digest) }
|
||||
if !noCache {
|
||||
markDownloadStarted(layer.digest)
|
||||
}
|
||||
|
||||
try await self.downloadLayer(
|
||||
repository: "\(self.organization)/\(imageName)",
|
||||
@@ -404,11 +410,14 @@ class ImageContainerRegistry: @unchecked Sendable {
|
||||
progress: progress
|
||||
)
|
||||
|
||||
// Cache the downloaded layer
|
||||
if FileManager.default.fileExists(atPath: cachedLayer.path) {
|
||||
try FileManager.default.removeItem(at: cachedLayer)
|
||||
// Cache the downloaded layer if not in noCache mode
|
||||
if !noCache {
|
||||
if FileManager.default.fileExists(atPath: cachedLayer.path) {
|
||||
try FileManager.default.removeItem(at: cachedLayer)
|
||||
}
|
||||
try FileManager.default.copyItem(at: outputURL, to: cachedLayer)
|
||||
markDownloadComplete(layer.digest)
|
||||
}
|
||||
try FileManager.default.copyItem(at: outputURL, to: cachedLayer)
|
||||
}
|
||||
|
||||
return Int64(layer.size)
|
||||
|
||||
@@ -316,7 +316,7 @@ final class LumeController {
|
||||
}
|
||||
|
||||
@MainActor
|
||||
public func pullImage(image: String, name: String?, registry: String, organization: String)
|
||||
public func pullImage(image: String, name: String?, registry: String, organization: String, noCache: Bool = false)
|
||||
async throws
|
||||
{
|
||||
do {
|
||||
@@ -336,7 +336,7 @@ final class LumeController {
|
||||
|
||||
let imageContainerRegistry = ImageContainerRegistry(
|
||||
registry: registry, organization: organization)
|
||||
try await imageContainerRegistry.pull(image: image, name: vmName)
|
||||
try await imageContainerRegistry.pull(image: image, name: vmName, noCache: noCache)
|
||||
|
||||
Logger.info("Setting new VM mac address")
|
||||
|
||||
|
||||
@@ -225,7 +225,7 @@ extension Server {
|
||||
|
||||
do {
|
||||
let vmController = LumeController()
|
||||
try await vmController.pullImage(image: request.image, name: request.name, registry: request.registry, organization: request.organization)
|
||||
try await vmController.pullImage(image: request.image, name: request.name, registry: request.registry, organization: request.organization, noCache: request.noCache)
|
||||
return HTTPResponse(
|
||||
statusCode: .ok,
|
||||
headers: ["Content-Type": "application/json"],
|
||||
@@ -322,4 +322,4 @@ extension Server {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,10 @@ struct PullRequest: Codable {
|
||||
let name: String?
|
||||
var registry: String
|
||||
var organization: String
|
||||
var noCache: Bool
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case image, name, registry, organization
|
||||
case image, name, registry, organization, noCache
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
@@ -48,6 +49,7 @@ struct PullRequest: Codable {
|
||||
name = try container.decodeIfPresent(String.self, forKey: .name)
|
||||
registry = try container.decodeIfPresent(String.self, forKey: .registry) ?? "ghcr.io"
|
||||
organization = try container.decodeIfPresent(String.self, forKey: .organization) ?? "trycua"
|
||||
noCache = try container.decodeIfPresent(Bool.self, forKey: .noCache) ?? false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,4 +93,4 @@ struct SetVMRequest: Codable {
|
||||
struct CloneRequest: Codable {
|
||||
let name: String
|
||||
let newName: String
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user