@@ -18,14 +18,18 @@ package container
18
18
19
19
import (
20
20
"fmt"
21
+ "os"
22
+ "slices"
21
23
"strings"
22
24
"testing"
23
25
24
26
"github.com/docker/go-connections/nat"
25
27
"gotest.tools/v3/assert"
26
28
29
+ "github.com/containerd/nerdctl/v2/pkg/infoutil"
27
30
"github.com/containerd/nerdctl/v2/pkg/inspecttypes/dockercompat"
28
31
"github.com/containerd/nerdctl/v2/pkg/labels"
32
+ "github.com/containerd/nerdctl/v2/pkg/rootlessutil"
29
33
"github.com/containerd/nerdctl/v2/pkg/testutil"
30
34
)
31
35
@@ -68,13 +72,12 @@ func TestContainerInspectContainsMounts(t *testing.T) {
68
72
testutil .NginxAlpineImage ).AssertOK ()
69
73
70
74
inspect := base .InspectContainer (testContainer )
71
-
72
75
// convert array to map to get by key of Destination
73
76
actual := make (map [string ]dockercompat.MountPoint )
74
77
for i := range inspect .Mounts {
75
78
actual [inspect .Mounts [i ].Destination ] = inspect .Mounts [i ]
76
79
}
77
-
80
+ t . Logf ( "actual in TestContainerInspectContainsMounts: %+v" , actual )
78
81
const localDriver = "local"
79
82
80
83
expected := []struct {
@@ -229,3 +232,234 @@ func TestContainerInspectState(t *testing.T) {
229
232
}
230
233
231
234
}
235
+
236
+ func TestContainerInspectHostConfig (t * testing.T ) {
237
+ testContainer := testutil .Identifier (t )
238
+ if rootlessutil .IsRootless () && infoutil .CgroupsVersion () == "1" {
239
+ t .Skip ("test skipped for rootless containers on cgroup v1" )
240
+ }
241
+
242
+ base := testutil .NewBase (t )
243
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
244
+
245
+ // Run a container with various HostConfig options
246
+ base .Cmd ("run" , "-d" , "--name" , testContainer ,
247
+ "--cpuset-cpus" , "0-1" ,
248
+ "--cpuset-mems" , "0" ,
249
+ "--blkio-weight" , "500" ,
250
+ "--cpu-shares" , "1024" ,
251
+ "--cpu-quota" , "100000" ,
252
+ "--group-add" , "1000" ,
253
+ "--group-add" , "2000" ,
254
+ "--add-host" , "host1:10.0.0.1" ,
255
+ "--add-host" , "host2:10.0.0.2" ,
256
+ "--ipc" , "host" ,
257
+ "--memory" , "512m" ,
258
+ "--read-only" ,
259
+ "--shm-size" , "256m" ,
260
+ "--uts" , "host" ,
261
+ "--sysctl" , "net.core.somaxconn=1024" ,
262
+ "--runtime" , "io.containerd.runc.v2" ,
263
+ testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
264
+
265
+ inspect := base .InspectContainer (testContainer )
266
+
267
+ assert .Equal (t , "0-1" , inspect .HostConfig .CPUSetCPUs )
268
+ assert .Equal (t , "0" , inspect .HostConfig .CPUSetMems )
269
+ assert .Equal (t , uint16 (500 ), inspect .HostConfig .BlkioWeight )
270
+ assert .Equal (t , uint64 (1024 ), inspect .HostConfig .CPUShares )
271
+ assert .Equal (t , int64 (100000 ), inspect .HostConfig .CPUQuota )
272
+ assert .Assert (t , slices .Contains (inspect .HostConfig .GroupAdd , "1000" ), "Expected '1000' to be in GroupAdd" )
273
+ assert .Assert (t , slices .Contains (inspect .HostConfig .GroupAdd , "2000" ), "Expected '2000' to be in GroupAdd" )
274
+ expectedExtraHosts := []string {"host1:10.0.0.1" , "host2:10.0.0.2" }
275
+ assert .DeepEqual (t , expectedExtraHosts , inspect .HostConfig .ExtraHosts )
276
+ assert .Equal (t , "host" , inspect .HostConfig .IpcMode )
277
+ assert .Equal (t , int64 (536870912 ), inspect .HostConfig .Memory )
278
+ assert .Equal (t , int64 (1073741824 ), inspect .HostConfig .MemorySwap )
279
+ assert .Equal (t , true , inspect .HostConfig .ReadonlyRootfs )
280
+ assert .Equal (t , "host" , inspect .HostConfig .UTSMode )
281
+ assert .Equal (t , int64 (268435456 ), inspect .HostConfig .ShmSize )
282
+ }
283
+
284
+ func TestContainerInspectHostConfigDefaults (t * testing.T ) {
285
+ testContainer := testutil .Identifier (t )
286
+
287
+ base := testutil .NewBase (t )
288
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
289
+
290
+ var hc hostConfigValues
291
+
292
+ // Hostconfig default values differ with Docker.
293
+ // This is because we directly retrieve the configured values instead of using preset defaults.
294
+ if testutil .GetTarget () == testutil .Docker {
295
+ hc .Driver = ""
296
+ hc .GroupAddSize = 0
297
+ hc .ShmSize = int64 (67108864 ) // Docker default 64M
298
+ hc .Runtime = "runc"
299
+ } else {
300
+ hc .GroupAddSize = 10
301
+ hc .Driver = "json-file"
302
+ hc .ShmSize = int64 (0 )
303
+ hc .Runtime = "io.containerd.runc.v2"
304
+ }
305
+
306
+ // Run a container without specifying HostConfig options
307
+ base .Cmd ("run" , "-d" , "--name" , testContainer , testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
308
+
309
+ inspect := base .InspectContainer (testContainer )
310
+ t .Logf ("HostConfig in TestContainerInspectHostConfigDefaults: %+v" , inspect .HostConfig )
311
+ assert .Equal (t , "" , inspect .HostConfig .CPUSetCPUs )
312
+ assert .Equal (t , "" , inspect .HostConfig .CPUSetMems )
313
+ assert .Equal (t , uint16 (0 ), inspect .HostConfig .BlkioWeight )
314
+ assert .Equal (t , uint64 (0 ), inspect .HostConfig .CPUShares )
315
+ assert .Equal (t , int64 (0 ), inspect .HostConfig .CPUQuota )
316
+ assert .Equal (t , hc .GroupAddSize , len (inspect .HostConfig .GroupAdd ))
317
+ assert .Equal (t , 0 , len (inspect .HostConfig .ExtraHosts ))
318
+ assert .Equal (t , "private" , inspect .HostConfig .IpcMode )
319
+ assert .Equal (t , hc .Driver , inspect .HostConfig .LogConfig .Driver )
320
+ assert .Equal (t , int64 (0 ), inspect .HostConfig .Memory )
321
+ assert .Equal (t , int64 (0 ), inspect .HostConfig .MemorySwap )
322
+ assert .Equal (t , bool (false ), inspect .HostConfig .OomKillDisable )
323
+ assert .Equal (t , bool (false ), inspect .HostConfig .ReadonlyRootfs )
324
+ assert .Equal (t , "" , inspect .HostConfig .UTSMode )
325
+ assert .Equal (t , hc .ShmSize , inspect .HostConfig .ShmSize )
326
+ assert .Equal (t , hc .Runtime , inspect .HostConfig .Runtime )
327
+ assert .Equal (t , 0 , len (inspect .HostConfig .Sysctls ))
328
+ assert .Equal (t , 0 , len (inspect .HostConfig .Devices ))
329
+ }
330
+
331
+ func TestContainerInspectHostConfigDNS (t * testing.T ) {
332
+ testContainer := testutil .Identifier (t )
333
+
334
+ base := testutil .NewBase (t )
335
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
336
+
337
+ // Run a container with DNS options
338
+ base .Cmd ("run" , "-d" , "--name" , testContainer ,
339
+ "--dns" , "8.8.8.8" ,
340
+ "--dns" , "1.1.1.1" ,
341
+ "--dns-search" , "example.com" ,
342
+ "--dns-search" , "test.local" ,
343
+ "--dns-option" , "ndots:5" ,
344
+ "--dns-option" , "timeout:3" ,
345
+ testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
346
+
347
+ inspect := base .InspectContainer (testContainer )
348
+
349
+ // Check DNS servers
350
+ expectedDNSServers := []string {"8.8.8.8" , "1.1.1.1" }
351
+ assert .DeepEqual (t , expectedDNSServers , inspect .HostConfig .DNS )
352
+
353
+ // Check DNS search domains
354
+ expectedDNSSearch := []string {"example.com" , "test.local" }
355
+ assert .DeepEqual (t , expectedDNSSearch , inspect .HostConfig .DNSSearch )
356
+
357
+ // Check DNS options
358
+ expectedDNSOptions := []string {"ndots:5" , "timeout:3" }
359
+ assert .DeepEqual (t , expectedDNSOptions , inspect .HostConfig .DNSOptions )
360
+ }
361
+
362
+ func TestContainerInspectHostConfigDNSDefaults (t * testing.T ) {
363
+ testContainer := testutil .Identifier (t )
364
+
365
+ base := testutil .NewBase (t )
366
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
367
+
368
+ // Run a container without specifying DNS options
369
+ base .Cmd ("run" , "-d" , "--name" , testContainer , testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
370
+
371
+ inspect := base .InspectContainer (testContainer )
372
+
373
+ // Check that DNS settings are empty by default
374
+ assert .Equal (t , 0 , len (inspect .HostConfig .DNS ))
375
+ assert .Equal (t , 0 , len (inspect .HostConfig .DNSSearch ))
376
+ assert .Equal (t , 0 , len (inspect .HostConfig .DNSOptions ))
377
+ }
378
+
379
+ func TestContainerInspectHostConfigPID (t * testing.T ) {
380
+ testContainer1 := testutil .Identifier (t ) + "-container1"
381
+ testContainer2 := testutil .Identifier (t ) + "-container2"
382
+
383
+ base := testutil .NewBase (t )
384
+ defer base .Cmd ("rm" , "-f" , testContainer1 , testContainer2 ).Run ()
385
+
386
+ // Run the first container
387
+ base .Cmd ("run" , "-d" , "--name" , testContainer1 , testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
388
+
389
+ containerID1 := strings .TrimSpace (base .Cmd ("inspect" , "-f" , "{{.Id}}" , testContainer1 ).Out ())
390
+
391
+ var hc hostConfigValues
392
+
393
+ if testutil .GetTarget () == testutil .Docker {
394
+ hc .PidMode = "container:" + containerID1
395
+ } else {
396
+ hc .PidMode = containerID1
397
+ }
398
+
399
+ base .Cmd ("run" , "-d" , "--name" , testContainer2 ,
400
+ "--pid" , fmt .Sprintf ("container:%s" , testContainer1 ),
401
+ testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
402
+
403
+ inspect := base .InspectContainer (testContainer2 )
404
+
405
+ assert .Equal (t , hc .PidMode , inspect .HostConfig .PidMode )
406
+
407
+ }
408
+
409
+ func TestContainerInspectHostConfigPIDDefaults (t * testing.T ) {
410
+ testContainer := testutil .Identifier (t )
411
+
412
+ base := testutil .NewBase (t )
413
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
414
+
415
+ base .Cmd ("run" , "-d" , "--name" , testContainer , testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
416
+
417
+ inspect := base .InspectContainer (testContainer )
418
+
419
+ assert .Equal (t , "" , inspect .HostConfig .PidMode )
420
+ }
421
+
422
+ func TestContainerInspectDevices (t * testing.T ) {
423
+ testContainer := testutil .Identifier (t )
424
+
425
+ base := testutil .NewBase (t )
426
+ defer base .Cmd ("rm" , "-f" , testContainer ).Run ()
427
+
428
+ if rootlessutil .IsRootless () && infoutil .CgroupsVersion () == "1" {
429
+ t .Skip ("test skipped for rootless containers on cgroup v1" )
430
+ }
431
+
432
+ // Create a temporary directory
433
+ dir , err := os .MkdirTemp (t .TempDir (), "device-dir" )
434
+ if err != nil {
435
+ t .Fatal (err )
436
+ }
437
+
438
+ if testutil .GetTarget () == testutil .Docker {
439
+ dir = "/dev/zero"
440
+ }
441
+
442
+ // Run the container with the directory mapped as a device
443
+ base .Cmd ("run" , "-d" , "--name" , testContainer ,
444
+ "--device" , dir + ":/dev/xvda" ,
445
+ testutil .AlpineImage , "sleep" , "infinity" ).AssertOK ()
446
+
447
+ inspect := base .InspectContainer (testContainer )
448
+
449
+ expectedDevices := []dockercompat.DeviceMapping {
450
+ {
451
+ PathOnHost : dir ,
452
+ PathInContainer : "/dev/xvda" ,
453
+ CgroupPermissions : "rwm" ,
454
+ },
455
+ }
456
+ assert .DeepEqual (t , expectedDevices , inspect .HostConfig .Devices )
457
+ }
458
+
459
+ type hostConfigValues struct {
460
+ Driver string
461
+ ShmSize int64
462
+ PidMode string
463
+ GroupAddSize int
464
+ Runtime string
465
+ }
0 commit comments