mirror of
https://github.com/apple/container.git
synced 2026-09-27 17:36:08 -04:00
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:
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerResource
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import ContainerizationOCI
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import AsyncHTTPClient
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import ContainerizationError
|
||||
import ContainerizationExtras
|
||||
import ContainerizationOS
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import AsyncHTTPClient
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import ContainerizationExtras
|
||||
import ContainerizationOS
|
||||
import Foundation
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import ContainerPersistence
|
||||
import ContainerizationArchive
|
||||
import Foundation
|
||||
@@ -81,7 +81,7 @@ class TestCLIKernelSet: CLITest {
|
||||
try await withTempDir { tempDir in
|
||||
// manually download the tar file
|
||||
let localTarPath = tempDir.appending(path: remoteTar.lastPathComponent)
|
||||
try await ContainerClient.FileDownloader.downloadFile(url: remoteTar, to: localTarPath)
|
||||
try await ContainerAPIClient.FileDownloader.downloadFile(url: remoteTar, to: localTarPath)
|
||||
|
||||
let extraArgs: [String] = [
|
||||
"--tar",
|
||||
@@ -113,7 +113,7 @@ class TestCLIKernelSet: CLITest {
|
||||
try await withTempDir { tempDir in
|
||||
// manually download the tar file
|
||||
let localTarPath = tempDir.appending(path: remoteTar.lastPathComponent)
|
||||
try await ContainerClient.FileDownloader.downloadFile(url: remoteTar, to: localTarPath)
|
||||
try await ContainerAPIClient.FileDownloader.downloadFile(url: remoteTar, to: localTarPath)
|
||||
|
||||
// extract just the file we want
|
||||
let targetPath = tempDir.appending(path: URL(string: defaultBinaryPath)!.lastPathComponent)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerResource
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerClient
|
||||
import ContainerAPIClient
|
||||
import ContainerizationOCI
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import AsyncHTTPClient
|
||||
import ContainerClient
|
||||
import ContainerNetworkService
|
||||
import ContainerResource
|
||||
import Containerization
|
||||
import ContainerizationOS
|
||||
import Foundation
|
||||
@@ -305,7 +304,7 @@ class CLITest {
|
||||
struct inspectOutput: Codable {
|
||||
let status: String
|
||||
let configuration: ContainerConfiguration
|
||||
let networks: [ContainerNetworkService.Attachment]
|
||||
let networks: [ContainerResource.Attachment]
|
||||
}
|
||||
|
||||
func getContainerStatus(_ name: String) throws -> String {
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -17,7 +17,7 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct DiskUsageTests {
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -18,7 +18,7 @@ import ContainerizationError
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct HostDNSResolverTest {
|
||||
@Test
|
||||
+2
-2
@@ -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.
|
||||
@@ -17,7 +17,7 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct MeasurementParseTests {
|
||||
|
||||
+2
-2
@@ -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.
|
||||
@@ -18,7 +18,7 @@ import ContainerizationError
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct ParserTest {
|
||||
@Test
|
||||
+2
-2
@@ -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.
|
||||
@@ -19,7 +19,7 @@ import ContainerizationError
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct RequestSchemeTests {
|
||||
static let defaultDnsDomain = DefaultsStore.get(key: .defaultDNSDomain)
|
||||
+18
-40
@@ -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,11 +14,12 @@
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import ContainerResource
|
||||
import ContainerizationError
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerAPIClient
|
||||
|
||||
struct UtilityTests {
|
||||
|
||||
@@ -90,44 +91,21 @@ struct UtilityTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
func testPublishPortsNonOverlapping() throws {
|
||||
let result = try Parser.publishPorts([
|
||||
"8080-8179:9000-9099/tcp",
|
||||
"8180-8279:9100-9199/tcp",
|
||||
func testPublishPortParser() throws {
|
||||
let ports = try Parser.publishPorts([
|
||||
"127.0.0.1:8000:9080",
|
||||
"8080-8179:9000-9099/udp",
|
||||
])
|
||||
#expect(result.count == 2)
|
||||
try Utility.validPublishPorts(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
func testPublishPortsOverlapping() throws {
|
||||
let result = try Parser.publishPorts([
|
||||
"9000-9100:8080-8180/tcp",
|
||||
"9100-9199:8180-8279/tcp",
|
||||
])
|
||||
#expect(result.count == 2)
|
||||
#expect {
|
||||
try Utility.validPublishPorts(result)
|
||||
} throws: { error in
|
||||
guard let error = error as? ContainerizationError else {
|
||||
return false
|
||||
}
|
||||
return error.description.contains("port specs may not overlap")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
func testPublishPortsSamePortDifferentProtocols() throws {
|
||||
let result = try Parser.publishPorts([
|
||||
"8080:8080/tcp",
|
||||
"8080:8080/udp",
|
||||
"1024-2048:1024-2048/tcp",
|
||||
"1024-2048:1024-2048/udp",
|
||||
"8081:8081",
|
||||
"8081:8081/udp",
|
||||
])
|
||||
#expect(result.count == 6)
|
||||
try Utility.validPublishPorts(result)
|
||||
#expect(ports.count == 2)
|
||||
#expect(ports[0].hostAddress == "127.0.0.1")
|
||||
#expect(ports[0].hostPort == 8000)
|
||||
#expect(ports[0].containerPort == 9080)
|
||||
#expect(ports[0].proto == .tcp)
|
||||
#expect(ports[0].count == 1)
|
||||
#expect(ports[1].hostAddress == "0.0.0.0")
|
||||
#expect(ports[1].hostPort == 8080)
|
||||
#expect(ports[1].containerPort == 9000)
|
||||
#expect(ports[1].proto == .udp)
|
||||
#expect(ports[1].count == 100)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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.
|
||||
@@ -18,7 +18,7 @@ import ContainerizationError
|
||||
import ContainerizationExtras
|
||||
import Testing
|
||||
|
||||
@testable import ContainerNetworkService
|
||||
@testable import ContainerResource
|
||||
|
||||
struct NetworkConfigurationTest {
|
||||
@Test func testValidationOkDefaults() throws {
|
||||
@@ -0,0 +1,51 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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.
|
||||
// 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
|
||||
import Testing
|
||||
|
||||
@testable import ContainerResource
|
||||
|
||||
struct PublshPortTests {
|
||||
@Test
|
||||
func testPublishPortsNonOverlapping() throws {
|
||||
let ports = [
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 9000, containerPort: 8080, proto: .tcp, count: 100),
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 9100, containerPort: 8180, proto: .tcp, count: 100),
|
||||
]
|
||||
#expect(!ports.hasOverlaps())
|
||||
}
|
||||
|
||||
@Test
|
||||
func testPublishPortsOverlapping() throws {
|
||||
let ports = [
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 9000, containerPort: 8080, proto: .tcp, count: 101),
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 9100, containerPort: 8180, proto: .tcp, count: 100),
|
||||
]
|
||||
#expect(ports.hasOverlaps())
|
||||
}
|
||||
|
||||
@Test
|
||||
func testPublishPortsSamePortDifferentProtocols() throws {
|
||||
let ports = [
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 8080, containerPort: 8080, proto: .tcp, count: 1),
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 8080, containerPort: 8080, proto: .udp, count: 1),
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 1024, containerPort: 1024, proto: .tcp, count: 1025),
|
||||
PublishPort(hostAddress: "0.0.0.0", hostPort: 1024, containerPort: 1024, proto: .udp, count: 1025),
|
||||
]
|
||||
#expect(!ports.hasOverlaps())
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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.
|
||||
@@ -17,7 +17,7 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@testable import ContainerClient
|
||||
@testable import ContainerResource
|
||||
|
||||
struct VolumeValidationTests {
|
||||
|
||||
Reference in New Issue
Block a user