github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/integration/container/devices_windows_test.go (about)

     1  package container // import "github.com/docker/docker/integration/container"
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	containertypes "github.com/docker/docker/api/types/container"
     8  	"github.com/docker/docker/integration/internal/container"
     9  	"github.com/docker/docker/testutil"
    10  	"gotest.tools/v3/assert"
    11  	"gotest.tools/v3/skip"
    12  )
    13  
    14  // TestWindowsDevices that Windows Devices are correctly propagated
    15  // via HostConfig.Devices through to the implementation in hcsshim.
    16  func TestWindowsDevices(t *testing.T) {
    17  	skip.If(t, testEnv.DaemonInfo.OSType != "windows")
    18  	ctx := setupTest(t)
    19  	apiClient := testEnv.APIClient()
    20  
    21  	testData := []struct {
    22  		doc                         string
    23  		devices                     []string
    24  		isolation                   containertypes.Isolation
    25  		expectedStartFailure        bool
    26  		expectedStartFailureMessage string
    27  		expectedExitCode            int
    28  		expectedStdout              string
    29  		expectedStderr              string
    30  	}{
    31  		{
    32  			doc:              "process/no device mounted",
    33  			isolation:        containertypes.IsolationProcess,
    34  			expectedExitCode: 1,
    35  		},
    36  		{
    37  			doc:            "process/class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    38  			devices:        []string{"class/5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    39  			isolation:      containertypes.IsolationProcess,
    40  			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
    41  		},
    42  		{
    43  			doc:            "process/class://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    44  			devices:        []string{"class://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    45  			isolation:      containertypes.IsolationProcess,
    46  			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
    47  		},
    48  		{
    49  			doc:            "process/vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    50  			devices:        []string{"vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    51  			isolation:      containertypes.IsolationProcess,
    52  			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
    53  		},
    54  		{
    55  			doc:              "hyperv/no device mounted",
    56  			isolation:        containertypes.IsolationHyperV,
    57  			expectedExitCode: 1,
    58  		},
    59  		{
    60  			doc:                         "hyperv/class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    61  			devices:                     []string{"class/5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    62  			isolation:                   containertypes.IsolationHyperV,
    63  			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
    64  			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
    65  			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
    66  		},
    67  		{
    68  			doc:                         "hyperv/class://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    69  			devices:                     []string{"class://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    70  			isolation:                   containertypes.IsolationHyperV,
    71  			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
    72  			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
    73  			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
    74  		},
    75  		{
    76  			doc:                         "hyperv/vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
    77  			devices:                     []string{"vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
    78  			isolation:                   containertypes.IsolationHyperV,
    79  			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
    80  			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
    81  			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
    82  		},
    83  	}
    84  
    85  	for _, d := range testData {
    86  		d := d
    87  		t.Run(d.doc, func(t *testing.T) {
    88  			t.Parallel()
    89  			ctx := testutil.StartSpan(ctx, t)
    90  			deviceOptions := []func(*container.TestContainerConfig){container.WithIsolation(d.isolation)}
    91  			for _, deviceName := range d.devices {
    92  				deviceOptions = append(deviceOptions, container.WithWindowsDevice(deviceName))
    93  			}
    94  
    95  			id := container.Create(ctx, t, apiClient, deviceOptions...)
    96  
    97  			// Hyper-V isolation is failing even with no actual devices added.
    98  			// TODO: Once https://github.com/moby/moby/issues/43395 is resolved,
    99  			// remove this skip.If and validate the expected behaviour under Hyper-V.
   100  			skip.If(t, d.isolation == containertypes.IsolationHyperV && !d.expectedStartFailure, "FIXME. HyperV isolation setup is probably incorrect in the test")
   101  
   102  			err := apiClient.ContainerStart(ctx, id, containertypes.StartOptions{})
   103  			if d.expectedStartFailure {
   104  				assert.ErrorContains(t, err, d.expectedStartFailureMessage)
   105  				return
   106  			}
   107  			assert.NilError(t, err)
   108  
   109  			// /Windows/System32/HostDriverStore is mounted from the host when class GUID 5B45201D-F2F2-4F3B-85BB-30FF1F953599
   110  			// is mounted. See `C:\windows\System32\containers\devices.def` on a Windows host for (slightly more) details.
   111  			res, err := container.Exec(ctx, apiClient, id, []string{
   112  				"sh", "-c",
   113  				"ls -d /Windows/System32/HostDriverStore/* | grep /Windows/System32/HostDriverStore/FileRepository",
   114  			})
   115  			assert.NilError(t, err)
   116  			assert.Equal(t, d.expectedExitCode, res.ExitCode)
   117  			if d.expectedExitCode == 0 {
   118  				assert.Equal(t, d.expectedStdout, strings.TrimSpace(res.Stdout()))
   119  				assert.Equal(t, d.expectedStderr, strings.TrimSpace(res.Stderr()))
   120  			}
   121  		})
   122  	}
   123  }