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  }