github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration/container/cdi_test.go (about) 1 package container // import "github.com/Prakhar-Agarwal-byte/moby/integration/container" 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "os" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 containertypes "github.com/Prakhar-Agarwal-byte/moby/api/types/container" 13 "github.com/Prakhar-Agarwal-byte/moby/integration/internal/container" 14 "github.com/Prakhar-Agarwal-byte/moby/pkg/stdcopy" 15 "github.com/Prakhar-Agarwal-byte/moby/testutil" 16 "github.com/Prakhar-Agarwal-byte/moby/testutil/daemon" 17 "gotest.tools/v3/assert" 18 is "gotest.tools/v3/assert/cmp" 19 "gotest.tools/v3/skip" 20 ) 21 22 func TestCreateWithCDIDevices(t *testing.T) { 23 skip.If(t, testEnv.DaemonInfo.OSType != "linux", "CDI devices are only supported on Linux") 24 skip.If(t, testEnv.IsRemoteDaemon, "cannot run cdi tests with a remote daemon") 25 26 ctx := testutil.StartSpan(baseContext, t) 27 28 cwd, err := os.Getwd() 29 assert.NilError(t, err) 30 d := daemon.New(t, daemon.WithExperimental()) 31 d.StartWithBusybox(ctx, t, "--cdi-spec-dir="+filepath.Join(cwd, "testdata", "cdi")) 32 defer d.Stop(t) 33 34 apiClient := d.NewClientT(t) 35 36 id := container.Run(ctx, t, apiClient, 37 container.WithCmd("/bin/sh", "-c", "env"), 38 container.WithCDIDevices("vendor1.com/device=foo"), 39 ) 40 defer apiClient.ContainerRemove(ctx, id, containertypes.RemoveOptions{Force: true}) 41 42 inspect, err := apiClient.ContainerInspect(ctx, id) 43 assert.NilError(t, err) 44 45 expectedRequests := []containertypes.DeviceRequest{ 46 { 47 Driver: "cdi", 48 DeviceIDs: []string{"vendor1.com/device=foo"}, 49 }, 50 } 51 assert.Check(t, is.DeepEqual(inspect.HostConfig.DeviceRequests, expectedRequests)) 52 53 reader, err := apiClient.ContainerLogs(ctx, id, containertypes.LogsOptions{ 54 ShowStdout: true, 55 }) 56 assert.NilError(t, err) 57 58 actualStdout := new(bytes.Buffer) 59 actualStderr := io.Discard 60 _, err = stdcopy.StdCopy(actualStdout, actualStderr, reader) 61 assert.NilError(t, err) 62 63 outlines := strings.Split(actualStdout.String(), "\n") 64 assert.Assert(t, is.Contains(outlines, "FOO=injected")) 65 } 66 67 func TestCDISpecDirsAreInSystemInfo(t *testing.T) { 68 skip.If(t, testEnv.DaemonInfo.OSType == "windows") // d.Start fails on Windows with `protocol not available` 69 // TODO: This restriction can be relaxed with https://github.com/moby/moby/pull/46158 70 skip.If(t, testEnv.IsRootless, "the t.TempDir test creates a folder with incorrect permissions for rootless") 71 72 testCases := []struct { 73 description string 74 config map[string]interface{} 75 experimental bool 76 specDirs []string 77 expectedInfoCDISpecDirs []string 78 }{ 79 { 80 description: "experimental no spec dirs specified returns default", 81 experimental: true, 82 specDirs: nil, 83 expectedInfoCDISpecDirs: []string{"/etc/cdi", "/var/run/cdi"}, 84 }, 85 { 86 description: "experimental specified spec dirs are returned", 87 experimental: true, 88 specDirs: []string{"/foo/bar", "/baz/qux"}, 89 expectedInfoCDISpecDirs: []string{"/foo/bar", "/baz/qux"}, 90 }, 91 { 92 description: "experimental empty string as spec dir returns empty slice", 93 experimental: true, 94 specDirs: []string{""}, 95 expectedInfoCDISpecDirs: []string{}, 96 }, 97 { 98 description: "experimental empty config option returns empty slice", 99 experimental: true, 100 config: map[string]interface{}{"cdi-spec-dirs": []string{}}, 101 expectedInfoCDISpecDirs: []string{}, 102 }, 103 { 104 description: "non-experimental no spec dirs specified returns empty slice", 105 experimental: false, 106 specDirs: nil, 107 expectedInfoCDISpecDirs: []string{}, 108 }, 109 { 110 description: "non-experimental specified spec dirs returns empty slice", 111 experimental: false, 112 specDirs: []string{"/foo/bar", "/baz/qux"}, 113 expectedInfoCDISpecDirs: []string{}, 114 }, 115 { 116 description: "non-experimental empty string as spec dir returns empty slice", 117 experimental: false, 118 specDirs: []string{""}, 119 expectedInfoCDISpecDirs: []string{}, 120 }, 121 { 122 description: "non-experimental empty config option returns empty slice", 123 experimental: false, 124 config: map[string]interface{}{"cdi-spec-dirs": []string{}}, 125 expectedInfoCDISpecDirs: []string{}, 126 }, 127 } 128 129 for _, tc := range testCases { 130 t.Run(tc.description, func(t *testing.T) { 131 var opts []daemon.Option 132 if tc.experimental { 133 opts = append(opts, daemon.WithExperimental()) 134 } 135 d := daemon.New(t, opts...) 136 137 var args []string 138 for _, specDir := range tc.specDirs { 139 args = append(args, "--cdi-spec-dir="+specDir) 140 } 141 if tc.config != nil { 142 configPath := filepath.Join(t.TempDir(), "daemon.json") 143 144 configFile, err := os.Create(configPath) 145 assert.NilError(t, err) 146 defer configFile.Close() 147 148 err = json.NewEncoder(configFile).Encode(tc.config) 149 assert.NilError(t, err) 150 151 args = append(args, "--config-file="+configPath) 152 } 153 d.Start(t, args...) 154 defer d.Stop(t) 155 156 info := d.Info(t) 157 158 assert.Check(t, is.DeepEqual(tc.expectedInfoCDISpecDirs, info.CDISpecDirs)) 159 }) 160 } 161 }