Skip to content

Commit 3eed0a2

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feat/chaos-1456-sandbox-runtime-config
2 parents 7ba1c9c + 64bd48b commit 3eed0a2

6 files changed

Lines changed: 69 additions & 9 deletions

File tree

Sources/ContainerCommands/Image/ImageList.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ extension Application {
4646

4747
public mutating func run() async throws {
4848
let containerSystemConfig: ContainerSystemConfig = try await ConfigurationLoader.load()
49-
try Self.validate(format: format, quiet: quiet, verbose: verbose)
49+
try Self.validate(quiet: quiet, verbose: verbose)
5050

5151
var images = try await ClientImage.list().filter { img in
5252
!Utility.isInfraImage(name: img.reference, builderImage: containerSystemConfig.build.image, initImage: containerSystemConfig.vminit.image)
@@ -76,14 +76,10 @@ extension Application {
7676
Output.emit(Output.renderTable(items))
7777
}
7878

79-
private static func validate(format: ListFormat, quiet: Bool, verbose: Bool) throws {
79+
private static func validate(quiet: Bool, verbose: Bool) throws {
8080
if quiet && verbose {
8181
throw ContainerizationError(.invalidArgument, message: "cannot use flag --quiet and --verbose together")
8282
}
83-
let modifier = quiet || verbose
84-
if modifier && format == .json {
85-
throw ContainerizationError(.invalidArgument, message: "cannot use flag --quiet or --verbose along with --format json")
86-
}
8783
}
8884

8985
private static func emitJSON(images: [ClientImage]) async throws {

Sources/ContainerCommands/Volume/VolumeList.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ extension Application.VolumeCommand {
4343
let volumes = try await ClientVolume.list()
4444

4545
if format == .json {
46-
try Output.emit(Output.renderJSON(volumes))
46+
let options = JSONOptions(dateEncodingStrategy: .iso8601)
47+
try Output.emit(Output.renderJSON(volumes, options: options))
4748
return
4849
}
4950

Sources/Services/ContainerAPIService/Client/Flags.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,21 @@ public struct Flags {
344344

345345
@Option(name: [.customLong("volume"), .short], help: "Bind mount a volume into the container")
346346
public var volumes: [String] = []
347+
348+
public func validate() throws {
349+
if dnsDisabled {
350+
let hasDNSConfig =
351+
!dns.nameservers.isEmpty
352+
|| dns.domain != nil
353+
|| !dns.options.isEmpty
354+
|| !dns.searchDomains.isEmpty
355+
if hasDNSConfig {
356+
throw ValidationError(
357+
"`--no-dns` cannot be used with DNS configuration flags (`--dns`, `--dns-domain`, `--dns-option`, `--dns-search`)"
358+
)
359+
}
360+
}
361+
}
347362
}
348363

349364
public struct Progress: ParsableArguments {

Tests/CLITests/Subcommands/Networks/TestCLINetwork.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,16 @@ class TestCLINetwork: CLITest {
265265
name,
266266
curlImage,
267267
"curl",
268+
"--connect-timeout",
269+
"5",
268270
"http://google.com",
269271
])
270272

271-
#expect(failed == 6, "external connection should fail")
273+
// hostOnly mode blocks off-host traffic; depending on whether vmnet/firewall
274+
// rejects (7) or drops (28) packets, or DNS itself can't reach an external
275+
// resolver (6), curl will fail with one of these codes.
276+
let hostOnlyBlockedCodes: Set<Int32> = [6, 7, 28]
277+
#expect(hostOnlyBlockedCodes.contains(failed), "external connection should fail")
272278
}
273279
}
274280

Tests/CLITests/Subcommands/Volumes/TestCLIAnonymousVolumes.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,9 @@ class TestCLIAnonymousVolumes: CLITest {
319319

320320
// Parse JSON to verify metadata
321321
let data = output.data(using: .utf8)!
322-
let volumes = try JSONDecoder().decode([Volume].self, from: data)
322+
let decoder = JSONDecoder()
323+
decoder.dateDecodingStrategy = .iso8601
324+
let volumes = try decoder.decode([Volume].self, from: data)
323325

324326
let anonVolume = volumes.first { $0.name == volumeName }
325327
#expect(anonVolume != nil, "should find anonymous volume in list")

Tests/ContainerAPIClientTests/ParserTest.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,4 +1296,44 @@ struct ParserTest {
12961296
#expect(result.cpus == 2)
12971297
#expect(result.memoryInBytes == 2048.mib())
12981298
}
1299+
1300+
// MARK: - DNS Flag Validation Tests
1301+
1302+
@Test
1303+
func testManagementFlagsRejectsNoDNSWithDNS() throws {
1304+
#expect(throws: (any Error).self) {
1305+
_ = try Flags.Management.parse(["--dns", "1.1.1.1", "--no-dns"])
1306+
}
1307+
}
1308+
1309+
@Test
1310+
func testManagementFlagsRejectsNoDNSWithDNSDomain() throws {
1311+
#expect(throws: (any Error).self) {
1312+
_ = try Flags.Management.parse(["--dns-domain", "example.com", "--no-dns"])
1313+
}
1314+
}
1315+
1316+
@Test
1317+
func testManagementFlagsRejectsNoDNSWithDNSSearch() throws {
1318+
#expect(throws: (any Error).self) {
1319+
_ = try Flags.Management.parse(["--dns-search", "example.com", "--no-dns"])
1320+
}
1321+
}
1322+
1323+
@Test
1324+
func testManagementFlagsRejectsNoDNSWithDNSOption() throws {
1325+
#expect(throws: (any Error).self) {
1326+
_ = try Flags.Management.parse(["--dns-option", "debug", "--no-dns"])
1327+
}
1328+
}
1329+
1330+
@Test
1331+
func testManagementFlagsAcceptsDNSAlone() throws {
1332+
_ = try Flags.Management.parse(["--dns", "1.1.1.1"])
1333+
}
1334+
1335+
@Test
1336+
func testManagementFlagsAcceptsNoDNSAlone() throws {
1337+
_ = try Flags.Management.parse(["--no-dns"])
1338+
}
12991339
}

0 commit comments

Comments
 (0)