Skip to content

Commit 3680dff

Browse files
authored
Merge branch 'main' into k8s-worker-provisioner
2 parents c8ff74b + ff5aa8a commit 3680dff

8 files changed

Lines changed: 72 additions & 81 deletions

File tree

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,11 +298,11 @@ define RUN_INTEGRATION
298298
CLITEST_LOG_ROOT=$(LOG_ROOT) && export CLITEST_LOG_ROOT ; \
299299
CLITEST_SCRATCH_ROOT=$(SCRATCH_ROOT) && export CLITEST_SCRATCH_ROOT ; \
300300
CONTAINER_CLI_PATH=$(ROOT_DIR)/bin/container && export CONTAINER_CLI_PATH ; \
301-
echo "==> Warmup pass" && \
301+
echo "==> Starting warmup tests" && \
302302
$(SWIFT) test $(INTEGRATION_SWIFT_EXTRA) -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) --filter "$(WARMUP_FILTER)" && \
303-
echo "==> Concurrent pass (width=$(PARALLEL_WIDTH))" && \
303+
echo "==> Starting $(words $(CONCURRENT_TEST_SUITES)) test suites concurrently (width=$(PARALLEL_WIDTH))" && \
304304
$(SWIFT) test $(INTEGRATION_SWIFT_EXTRA) -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) $(CONCURRENT_EVENT_STREAM_OPTS) --experimental-maximum-parallelization-width $(PARALLEL_WIDTH) --filter "$(CONCURRENT_FILTER)" && \
305-
echo "==> Global pass (serial)" && \
305+
echo "==> Starting $(words $(SERIAL_TEST_SUITES)) test suites serially" && \
306306
$(SWIFT) test $(INTEGRATION_SWIFT_EXTRA) -c $(BUILD_CONFIGURATION) $(SWIFT_CONFIGURATION) $(GLOBAL_EVENT_STREAM_OPTS) --experimental-maximum-parallelization-width 1 --filter "$(SERIAL_FILTER)" ; \
307307
exit_code=$$? ; \
308308
$(INTEGRATION_POST_TEST) \

Sources/Services/ContainerAPIService/Client/ClientImage.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ extension ClientImage {
247247
public static func pull(
248248
reference: String,
249249
platform: Platform? = nil,
250-
scheme: RequestScheme = .auto,
250+
scheme: RequestScheme = .https,
251251
containerSystemConfig: ContainerSystemConfig,
252252
progressUpdate: ProgressUpdateHandler? = nil,
253253
maxConcurrentDownloads: Int = 3
@@ -354,7 +354,7 @@ extension ClientImage {
354354
public static func fetch(
355355
reference: String,
356356
platform: Platform? = nil,
357-
scheme: RequestScheme = .auto,
357+
scheme: RequestScheme = .https,
358358
containerSystemConfig: ContainerSystemConfig,
359359
progressUpdate: ProgressUpdateHandler? = nil,
360360
maxConcurrentDownloads: Int = 3

Sources/Services/ContainerAPIService/Client/Flags.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ public struct Flags {
158158
self.scheme = scheme
159159
}
160160

161-
@Option(help: "Scheme to use when connecting to the container registry. One of (http, https, auto)")
162-
public var scheme: String = "auto"
161+
@Option(help: "Scheme to use when connecting to the container registry. One of (http, https)")
162+
public var scheme: String = "https"
163163
}
164164

165165
public struct Management: ParsableArguments {

Sources/Services/ContainerAPIService/Client/Parser.swift

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public struct Parser {
318318
let rlimits = try Parser.rlimits(processFlags.ulimits)
319319

320320
return .init(
321-
executable: commandToRun.first!,
321+
executable: commandToRun[0],
322322
arguments: [String](commandToRun.dropFirst()),
323323
environment: envvars,
324324
workingDirectory: workingDir,
@@ -340,11 +340,31 @@ public struct Parser {
340340
public static let defaultDirectives = ["type": "virtiofs"]
341341

342342
public static func tmpfsMounts(_ mounts: [String]) throws -> [Filesystem] {
343-
let mounts = mounts.dedupe()
344343
var result: [Filesystem] = []
345344
result.reserveCapacity(mounts.count)
345+
var seenDestinations: Set<String> = []
346+
346347
for tmpfs in mounts {
347-
let fs = Filesystem.tmpfs(destination: tmpfs, options: [])
348+
let parts = tmpfs.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false)
349+
let destination = String(parts[0])
350+
let options = parts.count == 2 ? String(parts[1]).split(separator: ",").map(String.init) : []
351+
352+
if destination.isEmpty {
353+
throw ContainerizationError(.invalidArgument, message: "mount destination cannot be empty")
354+
}
355+
356+
let filePath = FilePath(destination)
357+
guard filePath.isAbsolute else {
358+
throw ContainerizationError(.invalidArgument, message: "\(destination) is not an absolute path")
359+
}
360+
361+
let normalizedDest = filePath.lexicallyNormalized().string
362+
if seenDestinations.contains(normalizedDest) {
363+
continue
364+
}
365+
seenDestinations.insert(normalizedDest)
366+
367+
let fs = Filesystem.tmpfs(destination: destination, options: options)
348368
try validateMount(.filesystem(fs))
349369
result.append(fs)
350370
}

Sources/Services/ContainerAPIService/Client/RequestScheme.swift

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,12 @@ public enum RequestScheme: String, Sendable {
2424
case http = "http"
2525
case https = "https"
2626

27-
case auto = "auto"
28-
2927
public init(_ rawValue: String) throws {
3028
switch rawValue {
3129
case RequestScheme.http.rawValue:
3230
self = .http
3331
case RequestScheme.https.rawValue:
3432
self = .https
35-
case RequestScheme.auto.rawValue:
36-
self = .auto
3733
default:
3834
throw ContainerizationError(.invalidArgument, message: "unsupported scheme \(rawValue)")
3935
}
@@ -50,48 +46,6 @@ public enum RequestScheme: String, Sendable {
5046
switch self {
5147
case .http, .https:
5248
return self
53-
case .auto:
54-
return Self.isInternalHost(host: host, internalDnsDomain: internalDnsDomain) ? .http : .https
55-
}
56-
}
57-
58-
/// Checks if the given `host` string is a private IP address
59-
/// or a domain typically reachable only on the local system.
60-
public static func isInternalHost(host: String, internalDnsDomain: String?) -> Bool {
61-
// The localhost hostname is private.
62-
if host == "localhost" {
63-
return true
64-
}
65-
66-
// If hostname uses the provided DNS domain, treat it as private.
67-
if let internalDnsDomain {
68-
if host.hasSuffix(".\(internalDnsDomain)") {
69-
return true
70-
}
71-
}
72-
73-
// If it's any other hostname and not an IP address, it's not private access.
74-
guard let ipv4Address = try? IPv4Address(host) else {
75-
return false
7649
}
77-
78-
let ipv4Value = ipv4Address.value
79-
80-
// 10.0.0.0/8 and 127.0.0.0/8 are private CIDRs.
81-
if (ipv4Value & 0xff00_0000 == 0x0a00_0000) || (ipv4Value & 0xff00_0000 == 0x7f00_0000) {
82-
return true
83-
}
84-
85-
// 192.168.0.0/16 is a private CIDR.
86-
if ipv4Value & 0xffff_0000 == 0xc0a8_0000 {
87-
return true
88-
}
89-
90-
// 172.16.0.0/12 is a private CIDR.
91-
if ipv4Value & 0xfff0_0000 == 0xac10_0000 {
92-
return true
93-
}
94-
95-
return false
9650
}
9751
}

Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ public actor VolumesService {
174174
)
175175
}
176176

177-
let volumePath = self.volumePath(for: name)
178-
return FileManager.default.allocatedSize(of: URL(fileURLWithPath: volumePath))
177+
return try await self._volumeDiskUsage(name)
179178
}
180179

181180
/// Calculate disk usage for volumes
@@ -403,4 +402,12 @@ public actor VolumesService {
403402
return volume
404403
}
405404

405+
private func _volumeDiskUsage(_ name: String) async throws -> UInt64 {
406+
guard VolumeStorage.isValidVolumeName(name) else {
407+
throw VolumeError.invalidVolumeName("invalid volume name '\(name)': must match \(VolumeStorage.volumeNamePattern)")
408+
}
409+
410+
let volumePath = self.volumePath(for: name)
411+
return FileManager.default.allocatedSize(of: URL(fileURLWithPath: volumePath))
412+
}
406413
}

Tests/ContainerAPIClientTests/ParserTest.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,33 @@ struct ParserTest {
15231523
#expect(result.count == 20)
15241524
}
15251525

1526+
@Test("tmpfsMounts parses mount options and dedupes on destination path")
1527+
func testTmpfsMountsWithColons() throws {
1528+
let mounts = [
1529+
"/mnt/scratch:rw,exec",
1530+
"/mnt/scratch", // Should be deduped based on path
1531+
"/mnt/cache:ro",
1532+
]
1533+
let result = try Parser.tmpfsMounts(mounts)
1534+
#expect(result.count == 2)
1535+
#expect(result[0].destination == "/mnt/scratch")
1536+
#expect(result[0].options == ["rw", "exec"])
1537+
}
1538+
1539+
@Test("tmpfsMounts throws on empty destination")
1540+
func testTmpfsMountsEmptyDestination() throws {
1541+
#expect(throws: ContainerizationError.self) {
1542+
_ = try Parser.tmpfsMounts([""])
1543+
}
1544+
}
1545+
1546+
@Test("tmpfsMounts throws on non-absolute destination")
1547+
func testTmpfsMountsNonAbsoluteDestination() throws {
1548+
#expect(throws: ContainerizationError.self) {
1549+
_ = try Parser.tmpfsMounts(["relative/path:rw"])
1550+
}
1551+
}
1552+
15261553
@Test("volumes with large input")
15271554
func testVolumesLargeInput() throws {
15281555
let volumes = (0..<20).map { "vol\($0):/mnt/vol\($0)" }

Tests/ContainerAPIClientTests/RequestSchemeTests.swift

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,28 @@ struct RequestSchemeTests {
3131
@Test(arguments: [
3232
TestArg(scheme: "http", host: "myregistry.io", expected: .http),
3333
TestArg(scheme: "https", host: "myregistry.io", expected: .https),
34-
TestArg(scheme: "auto", host: "myregistry.io", expected: .https),
3534
TestArg(scheme: "https", host: "localhost", expected: .https),
3635
TestArg(scheme: "http", host: "localhost", expected: .http),
37-
TestArg(scheme: "auto", host: "localhost", expected: .http),
38-
TestArg(scheme: "auto", host: "localhost.evil.com", expected: .https),
3936
TestArg(scheme: "http", host: "127.0.0.1", expected: .http),
4037
TestArg(scheme: "https", host: "127.0.0.1", expected: .https),
41-
TestArg(scheme: "auto", host: "127.0.0.1", expected: .http),
42-
TestArg(scheme: "auto", host: "127.255.255.255", expected: .http),
43-
TestArg(scheme: "auto", host: "127.0.0.1.evil.com", expected: .https),
4438
TestArg(scheme: "https", host: "10.3.4.1", expected: .https),
45-
TestArg(scheme: "auto", host: "10.3.4.1", expected: .http),
46-
TestArg(scheme: "auto", host: "10.255.255.255", expected: .http),
47-
TestArg(scheme: "auto", host: "10.0.0.1.evil.com", expected: .https),
48-
TestArg(scheme: "auto", host: "192.168.0.1", expected: .http),
49-
TestArg(scheme: "auto", host: "192.168.255.255", expected: .http),
50-
TestArg(scheme: "auto", host: "192.169.0.1", expected: .https),
51-
TestArg(scheme: "auto", host: "192.168.1.1.evil.com", expected: .https),
52-
TestArg(scheme: "auto", host: "some-dns-name.io", expected: .https),
53-
TestArg(scheme: "auto", host: "172.32.0.1", expected: .https),
54-
TestArg(scheme: "auto", host: "172.22.23.61", expected: .http),
55-
TestArg(scheme: "auto", host: "172.16.0.0", expected: .http),
56-
TestArg(scheme: "auto", host: "172.31.255.255", expected: .http),
5739
])
5840

5941
func testIsConnectionSecure(arg: TestArg) throws {
60-
let requestScheme = RequestScheme(rawValue: arg.scheme)!
42+
let requestScheme = try RequestScheme(arg.scheme)
6143
#expect(try requestScheme.schemeFor(host: arg.host, internalDnsDomain: Self.defaultDnsDomain) == arg.expected)
6244
}
6345

6446
@Test func testEmptyHostThrowsError() throws {
6547
#expect(throws: (any Error).self) {
66-
let requestScheme = RequestScheme(rawValue: "https")!
48+
let requestScheme = try RequestScheme("https")
6749
_ = try requestScheme.schemeFor(host: "", internalDnsDomain: Self.defaultDnsDomain)
6850
}
6951
}
7052

71-
@Test func testIsInternalHostWithDefaultDNSDomain() throws {
72-
let hostName = "some-dns-name.io.\(Self.defaultDnsDomain)"
73-
#expect(RequestScheme.isInternalHost(host: hostName, internalDnsDomain: Self.defaultDnsDomain))
53+
@Test func testUnsupportedSchemeThrowsError() throws {
54+
#expect(throws: (any Error).self) {
55+
_ = try RequestScheme("auto")
56+
}
7457
}
7558
}

0 commit comments

Comments
 (0)