Reorganize client libraries. (#1020)

- Closes #461.
- Extract core types into ContainerResources target.
- Extract ContainerNetworkServiceClient from ContainerNetworkService.
- Relocate sandbox client from ContainerClient to
ContainerSandboxServiceClient.
- Relocate ContainerClient to ContainerAPIServiceClient.
- Common structure from services and clients under Source/Services.

Updated project hierarchy:

```
Sources/CAuditToken - audit token access wrapper
Sources/CLI - CLI executable
Sources/ContainerBuild - builder
Sources/ContainerCommands - CLI command implementations
Sources/ContainerLog - logging helpers
Sources/ContainerPersistence - persistent data and system property helpers
Sources/ContainerPlugin - plugin system
Sources/ContainerResource - resource (container, image, volume, network) types
Sources/ContainerVersion - version helpers
Sources/ContainerXPC - XPC helpers
Sources/CVersion - injected project version
Sources/DNSServer - container DNS resolver
Sources/Helpers - service executables
Sources/Services/*/Client - service clients
Sources/Services/*/Server - service implementations
Sources/SocketForwarder - port forwarding
Sources/TerminalProgress - progress bar
```

## Type of Change
- [ ] Bug fix
- [ ] New feature  
- [x] Breaking change
- [ ] Documentation update

## Motivation and Context
The ContainerClient library was a bit of a grab bag. This refactor
applies a more sensible project and library structure for resource data
types, services, and clients.

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
This commit is contained in:
J Logan authored and GitHub committed 2026-01-06 08:27:14 -08:00
1 parent 8c439cd356
commit 356c8d2f88
165 files changed
+643 -472

No files matched your search

+6 -1
View File
@@ -3,10 +3,15 @@ builder:
configs:
-
documentation_targets:
- ContainerAPIService
- ContainerAPIClient
- ContainerSandboxService
- ContainerSandboxServiceClient
- ContainerNetworkService
- ContainerNetworkServiceClient
- ContainerImagesService
- ContainerClient
- ContainerImagesServiceClient
- ContainerResource
- ContainerLog
- ContainerPlugin
- ContainerXPC
+162 -116
View File
@@ -29,13 +29,14 @@ let package = Package(
name: "container",
platforms: [.macOS("15")],
products: [
.library(name: "ContainerAPIService", targets: ["ContainerAPIService"]),
.library(name: "ContainerSandboxService", targets: ["ContainerSandboxService"]),
.library(name: "ContainerNetworkService", targets: ["ContainerNetworkService"]),
.library(name: "ContainerImagesService", targets: ["ContainerImagesService", "ContainerImagesServiceClient"]),
.library(name: "ContainerCommands", targets: ["ContainerCommands"]),
.library(name: "ContainerClient", targets: ["ContainerClient"]),
.library(name: "ContainerBuild", targets: ["ContainerBuild"]),
.library(name: "ContainerAPIService", targets: ["ContainerAPIService"]),
.library(name: "ContainerAPIClient", targets: ["ContainerAPIClient"]),
.library(name: "ContainerImagesService", targets: ["ContainerImagesService", "ContainerImagesServiceClient"]),
.library(name: "ContainerNetworkService", targets: ["ContainerNetworkService", "ContainerNetworkServiceClient"]),
.library(name: "ContainerSandboxService", targets: ["ContainerSandboxService", "ContainerSandboxServiceClient"]),
.library(name: "ContainerResource", targets: ["ContainerResource"]),
.library(name: "ContainerLog", targets: ["ContainerLog"]),
.library(name: "ContainerPersistence", targets: ["ContainerPersistence"]),
.library(name: "ContainerPlugin", targets: ["ContainerPlugin"]),
@@ -61,11 +62,23 @@ let package = Package(
name: "container",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerClient",
"ContainerAPIClient",
"ContainerCommands",
],
path: "Sources/CLI"
),
.testTarget(
name: "CLITests",
dependencies: [
.product(name: "AsyncHTTPClient", package: "async-http-client"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerBuild",
"ContainerResource",
],
path: "Tests/CLITests"
),
.target(
name: "ContainerCommands",
dependencies: [
@@ -76,15 +89,34 @@ let package = Package(
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerBuild",
"ContainerClient",
"ContainerAPIClient",
"ContainerLog",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
"ContainerVersion",
"TerminalProgress",
],
path: "Sources/ContainerCommands"
),
.target(
name: "ContainerBuild",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "NIO", package: "swift-nio"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerAPIClient",
]
),
.testTarget(
name: "ContainerBuildTests",
dependencies: [
"ContainerBuild"
]
),
.executableTarget(
name: "container-apiserver",
dependencies: [
@@ -96,11 +128,12 @@ let package = Package(
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "Logging", package: "swift-log"),
"ContainerAPIService",
"ContainerClient",
"ContainerAPIClient",
"ContainerLog",
"ContainerNetworkService",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
"ContainerVersion",
"ContainerXPC",
"DNSServer",
@@ -111,83 +144,49 @@ let package = Package(
name: "ContainerAPIService",
dependencies: [
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "Logging", package: "swift-log"),
"ContainerClient",
"ContainerNetworkService",
"CVersion",
"ContainerAPIClient",
"ContainerNetworkServiceClient",
"ContainerPersistence",
"ContainerPlugin",
"ContainerSandboxService",
"ContainerResource",
"ContainerSandboxServiceClient",
"ContainerVersion",
"ContainerXPC",
"CVersion",
"TerminalProgress",
],
path: "Sources/Services/ContainerAPIService"
),
.executableTarget(
name: "container-runtime-linux",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "Containerization", package: "containerization"),
"ContainerLog",
"ContainerNetworkService",
"ContainerSandboxService",
"ContainerVersion",
"ContainerXPC",
],
path: "Sources/Helpers/RuntimeLinux"
path: "Sources/Services/ContainerAPIService/Server"
),
.target(
name: "ContainerSandboxService",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerClient",
"ContainerNetworkService",
"ContainerPersistence",
"ContainerXPC",
"SocketForwarder",
],
path: "Sources/Services/ContainerSandboxService"
),
.executableTarget(
name: "container-network-vmnet",
name: "ContainerAPIClient",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOPosix", package: "swift-nio"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationIO", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerLog",
"ContainerNetworkService",
"ContainerVersion",
"ContainerXPC",
],
path: "Sources/Helpers/NetworkVmnet"
),
.target(
name: "ContainerNetworkService",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerImagesServiceClient",
"ContainerPersistence",
"ContainerPlugin",
"ContainerResource",
"ContainerXPC",
"TerminalProgress",
],
path: "Sources/Services/ContainerNetworkService"
path: "Sources/Services/ContainerAPIService/Client"
),
.testTarget(
name: "ContainerNetworkServiceTests",
name: "ContainerAPIClientTests",
dependencies: [
"ContainerNetworkService"
.product(name: "Containerization", package: "containerization"),
"ContainerAPIClient",
"ContainerPersistence",
]
),
.executableTarget(
@@ -209,10 +208,17 @@ let package = Package(
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
"ContainerXPC",
"ContainerLog",
"ContainerClient",
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerAPIClient",
"ContainerImagesServiceClient",
"ContainerLog",
"ContainerPersistence",
"ContainerResource",
"ContainerXPC",
"TerminalProgress",
],
path: "Sources/Services/ContainerImagesService/Server"
),
@@ -226,48 +232,107 @@ let package = Package(
],
path: "Sources/Services/ContainerImagesService/Client"
),
.target(
name: "ContainerBuild",
.executableTarget(
name: "container-network-vmnet",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "NIO", package: "swift-nio"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerClient",
]
),
.testTarget(
name: "ContainerBuildTests",
dependencies: [
"ContainerBuild"
]
),
.target(
name: "ContainerClient",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOPosix", package: "swift-nio"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationOCI", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationIO", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "ContainerizationArchive", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerImagesServiceClient",
"ContainerLog",
"ContainerNetworkService",
"ContainerPlugin",
"ContainerNetworkServiceClient",
"ContainerResource",
"ContainerVersion",
"ContainerXPC",
"TerminalProgress",
],
path: "Sources/Helpers/NetworkVmnet"
),
.target(
name: "ContainerNetworkService",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerNetworkServiceClient",
"ContainerPersistence",
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/ContainerNetworkService/Server"
),
.target(
name: "ContainerNetworkServiceClient",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
"ContainerLog",
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/ContainerNetworkService/Client"
),
.executableTarget(
name: "container-runtime-linux",
dependencies: [
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "Logging", package: "swift-log"),
.product(name: "GRPC", package: "grpc-swift"),
.product(name: "Containerization", package: "containerization"),
"ContainerLog",
"ContainerResource",
"ContainerSandboxService",
"ContainerSandboxServiceClient",
"ContainerVersion",
"ContainerXPC",
],
path: "Sources/Helpers/RuntimeLinux"
),
.target(
name: "ContainerSandboxService",
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
"ContainerAPIClient",
"ContainerNetworkServiceClient",
"ContainerPersistence",
"ContainerResource",
"ContainerSandboxServiceClient",
"ContainerXPC",
"SocketForwarder",
],
path: "Sources/Services/ContainerSandboxService/Server"
),
.target(
name: "ContainerSandboxServiceClient",
dependencies: [
"ContainerResource",
"ContainerXPC",
],
path: "Sources/Services/ContainerSandboxService/Client"
),
.target(
name: "ContainerResource",
dependencies: [
.product(name: "Containerization", package: "containerization")
]
),
.testTarget(
name: "ContainerClientTests",
name: "ContainerResourceTests",
dependencies: [
.product(name: "Containerization", package: "containerization"),
"ContainerClient",
"ContainerPersistence",
"ContainerResource",
]
),
.target(
name: "ContainerLog",
dependencies: [
.product(name: "Logging", package: "swift-log")
]
),
.target(
@@ -275,8 +340,8 @@ let package = Package(
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "Containerization", package: "containerization"),
"ContainerVersion",
"CVersion",
"ContainerVersion",
]
),
.target(
@@ -293,12 +358,6 @@ let package = Package(
"ContainerPlugin"
]
),
.target(
name: "ContainerLog",
dependencies: [
.product(name: "Logging", package: "swift-log")
]
),
.target(
name: "ContainerXPC",
dependencies: [
@@ -347,19 +406,6 @@ let package = Package(
name: "SocketForwarderTests",
dependencies: ["SocketForwarder"]
),
.testTarget(
name: "CLITests",
dependencies: [
.product(name: "AsyncHTTPClient", package: "async-http-client"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationExtras", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"ContainerBuild",
"ContainerClient",
"ContainerNetworkService",
],
path: "Tests/CLITests"
),
.target(
name: "ContainerVersion",
dependencies: [
+1 -1
View File
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerCommands
@main
+1 -1
View File
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import Collections
import ContainerClient
import ContainerAPIClient
import ContainerizationArchive
import ContainerizationOCI
import Foundation
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationOCI
import Foundation
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationArchive
import ContainerizationOCI
+1 -1
View File
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationOCI
import ContainerizationOS
+1 -1
View File
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerLog
import ContainerPlugin
import ContainerVersion
+1 -1
View File
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerAPIClient
import ContainerBuild
import ContainerClient
import ContainerImagesServiceClient
import Containerization
import ContainerizationError
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
@@ -15,10 +15,10 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerAPIClient
import ContainerBuild
import ContainerClient
import ContainerNetworkService
import ContainerPersistence
import ContainerResource
import Containerization
import ContainerizationError
import ContainerizationExtras
@@ -164,7 +164,7 @@ extension Application {
].compactMap { $0 }
let id = "buildkit"
try ContainerClient.Utility.validEntityName(id)
try ContainerAPIClient.Utility.validEntityName(id)
let image = try await ClientImage.fetch(
reference: builderImage,
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationExtras
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import Foundation
import TerminalProgress
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationOS
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Foundation
import SwiftProtobuf
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationOS
import Darwin
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerNetworkService
import ContainerAPIClient
import ContainerResource
import ContainerizationExtras
import Foundation
import SwiftProtobuf
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Darwin
import Dispatch
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import Containerization
import ContainerizationError
import ContainerizationExtras
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationOS
import TerminalProgress
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import ContainerizationExtras
import Foundation
@@ -148,8 +149,8 @@ extension Application {
private struct StatsSnapshot {
let container: ClientContainer
let stats1: ContainerClient.ContainerStats
let stats2: ContainerClient.ContainerStats
let stats1: ContainerResource.ContainerStats
let stats2: ContainerResource.ContainerStats
}
private func collectStats(for containers: [ClientContainer]) async throws -> [StatsSnapshot] {
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import ContainerizationOS
import Foundation
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationError
import ContainerizationOS
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPlugin
import Darwin
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
import SwiftProtobuf
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationError
import ContainerizationOCI
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationOCI
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationOCI
import TerminalProgress
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationOCI
import TerminalProgress
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import Containerization
import ContainerizationError
import ContainerizationOCI
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
extension Application {
public struct ImageTag: AsyncParsableCommand {
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerNetworkService
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import ContainerizationExtras
import Foundation
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerNetworkService
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import Foundation
@@ -15,8 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerNetworkService
import ContainerAPIClient
import Foundation
import SwiftProtobuf
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerNetworkService
import ContainerAPIClient
import ContainerResource
import ContainerizationExtras
import Foundation
import SwiftProtobuf
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Foundation
extension Application.NetworkCommand {
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationError
import ContainerizationOCI
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Containerization
import ContainerizationOCI
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationExtras
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Foundation
extension Application {
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import Containerization
import ContainerizationError
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import ContainerizationError
import ContainerizationExtras
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerizationError
import ContainerizationOS
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPersistence
import ContainerPlugin
import ContainerizationError
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPlugin
import ContainerizationError
import Foundation
@@ -15,8 +15,9 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerPlugin
import ContainerResource
import ContainerizationOS
import Foundation
import Logging
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerVersion
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Foundation
extension Application.VolumeCommand {
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import ContainerizationError
import Foundation
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import Foundation
extension Application.VolumeCommand {
@@ -15,7 +15,8 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import ContainerResource
import ContainerizationExtras
import Foundation
@@ -15,7 +15,7 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerAPIClient
import Foundation
extension Application.VolumeCommand {
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerizationOCI
public struct ContainerConfiguration: Sendable, Codable {
@@ -83,16 +82,8 @@ public struct ContainerConfiguration: Sendable, Codable {
labels = try container.decodeIfPresent([String: String].self, forKey: .labels) ?? [:]
sysctls = try container.decodeIfPresent([String: String].self, forKey: .sysctls) ?? [:]
// NOTE: migrates [String] to [AttachmentConfiguration]; remove [String] support in a later release
if container.contains(.networks) {
do {
networks = try container.decode([AttachmentConfiguration].self, forKey: .networks)
} catch {
let networkIds = try container.decode([String].self, forKey: .networks)
// Parse old network IDs as simple network names without properties
let parsedNetworks = networkIds.map { Parser.ParsedNetwork(name: $0, macAddress: nil) }
networks = try Utility.getAttachmentConfigurations(containerId: id, networks: parsedNetworks)
}
networks = try container.decode([AttachmentConfiguration].self, forKey: .networks)
} else {
networks = []
}
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,8 +14,6 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
/// A snapshot of a container along with its configuration
/// and any runtime state information.
public struct ContainerSnapshot: Codable, Sendable {
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -72,3 +72,19 @@ public struct PublishPort: Sendable, Codable {
count = try container.decodeIfPresent(UInt16.self, forKey: .count) ?? 1
}
}
extension [PublishPort] {
public func hasOverlaps() -> Bool {
var hostPorts = Set<String>()
for publishPort in self {
for index in publishPort.hostPort..<(publishPort.hostPort + publishPort.count) {
let hostPortKey = "\(index)/\(publishPort.proto.rawValue)"
guard !hostPorts.contains(hostPortKey) else {
return true
}
hostPorts.insert(hostPortKey)
}
}
return false
}
}
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -27,40 +27,16 @@ public struct ImageDetail: Codable {
public let config: ContainerizationOCI.Image
public let size: Int64
init(platform: Platform, size: Int64, config: ContainerizationOCI.Image) {
public init(platform: Platform, size: Int64, config: ContainerizationOCI.Image) {
self.platform = platform
self.config = config
self.size = size
}
}
init(name: String, index: Descriptor, variants: [Variants]) {
public init(name: String, index: Descriptor, variants: [Variants]) {
self.name = name
self.index = index
self.variants = variants
}
}
extension ClientImage {
public func details() async throws -> ImageDetail {
let descriptor = try await self.resolved()
let reference = self.reference
var variants: [ImageDetail.Variants] = []
for desc in try await self.index().manifests {
guard let platform = desc.platform else {
continue
}
let config: ContainerizationOCI.Image
let manifest: ContainerizationOCI.Manifest
do {
config = try await self.config(for: platform)
manifest = try await self.manifest(for: platform)
} catch {
continue
}
let size = desc.size + manifest.config.size + manifest.layers.reduce(0, { (l, r) in l + r.size })
variants.append(.init(platform: platform, size: size, config: config))
}
return ImageDetail(name: reference, index: descriptor, variants: variants)
}
}
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,10 +15,11 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerAPIClient
import ContainerAPIService
import ContainerClient
import ContainerNetworkService
import ContainerPlugin
import ContainerResource
import ContainerXPC
import DNSServer
import Foundation
@@ -16,6 +16,8 @@
import ArgumentParser
import ContainerNetworkService
import ContainerNetworkServiceClient
import ContainerResource
import ContainerXPC
import ContainerizationExtras
import Foundation
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerResource
import ContainerSandboxService
import ContainerXPC
import Containerization
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerResource
import ContainerSandboxService
import ContainerXPC
import Containerization
@@ -15,9 +15,10 @@
//===----------------------------------------------------------------------===//
import ArgumentParser
import ContainerClient
import ContainerLog
import ContainerResource
import ContainerSandboxService
import ContainerSandboxServiceClient
import ContainerXPC
import Foundation
import Logging
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerResource
import ContainerXPC
import Containerization
import ContainerizationError
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
import ContainerImagesServiceClient
import ContainerPersistence
import ContainerResource
import ContainerXPC
import Containerization
import ContainerizationError
@@ -498,3 +499,27 @@ extension ImageDescription {
return name
}
}
extension ClientImage {
public func details() async throws -> ImageDetail {
let descriptor = try await self.resolved()
let reference = self.reference
var variants: [ImageDetail.Variants] = []
for desc in try await self.index().manifests {
guard let platform = desc.platform else {
continue
}
let config: ContainerizationOCI.Image
let manifest: ContainerizationOCI.Manifest
do {
config = try await self.config(for: platform)
manifest = try await self.manifest(for: platform)
} catch {
continue
}
let size = desc.size + manifest.config.size + manifest.layers.reduce(0, { (l, r) in l + r.size })
variants.append(.init(platform: platform, size: size, config: config))
}
return ImageDetail(name: reference, index: descriptor, variants: variants)
}
}
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerResource
import ContainerXPC
import ContainerizationError
import ContainerizationOS
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerNetworkService
import ContainerXPC
import Containerization
import ContainerizationError
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//
import ContainerResource
import ContainerXPC
import Containerization
import Foundation
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
//===----------------------------------------------------------------------===//
// Copyright © 2025-2026 Apple Inc. and the container project authors.
// Copyright © 2026 Apple Inc. and the container project authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Loaded 100 of 165 files, more files were not shown because too many files have changed in this diff. Show more