summaryrefslogtreecommitdiff
path: root/integration/container/devices_windows_test.go
blob: 1ab5c6e690fcb93f2d1fcab3bcda46182b25a5da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package container // import "github.com/docker/docker/integration/container"

import (
	"context"
	"strings"
	"testing"
	"time"

	"github.com/docker/docker/api/types"
	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/integration/internal/container"
	"gotest.tools/v3/assert"
	"gotest.tools/v3/poll"
	"gotest.tools/v3/skip"
)

// TestWindowsDevices that Windows Devices are correctly propagated
// via HostConfig.Devices through to the implementation in hcsshim.
func TestWindowsDevices(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType != "windows")
	defer setupTest(t)()
	client := testEnv.APIClient()
	ctx := context.Background()

	testData := []struct {
		doc                         string
		devices                     []string
		isolation                   containertypes.Isolation
		expectedStartFailure        bool
		expectedStartFailureMessage string
		expectedExitCode            int
		expectedStdout              string
		expectedStderr              string
	}{
		{
			doc:              "process/no device mounted",
			isolation:        containertypes.IsolationProcess,
			expectedExitCode: 1,
		},
		{
			doc:            "process/class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:        []string{"class/5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:      containertypes.IsolationProcess,
			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
		},
		{
			doc:            "process/class://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:        []string{"class://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:      containertypes.IsolationProcess,
			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
		},
		{
			doc:            "process/vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:        []string{"vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:      containertypes.IsolationProcess,
			expectedStdout: "/Windows/System32/HostDriverStore/FileRepository",
		},
		{
			doc:              "hyperv/no device mounted",
			isolation:        containertypes.IsolationHyperV,
			expectedExitCode: 1,
		},
		{
			doc:                         "hyperv/class/5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:                     []string{"class/5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:                   containertypes.IsolationHyperV,
			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
		},
		{
			doc:                         "hyperv/class://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:                     []string{"class://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:                   containertypes.IsolationHyperV,
			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
		},
		{
			doc:                         "hyperv/vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599 mounted",
			devices:                     []string{"vpci-class-guid://5B45201D-F2F2-4F3B-85BB-30FF1F953599"},
			isolation:                   containertypes.IsolationHyperV,
			expectedStartFailure:        !testEnv.RuntimeIsWindowsContainerd(),
			expectedStartFailureMessage: "device assignment is not supported for HyperV containers",
			expectedStdout:              "/Windows/System32/HostDriverStore/FileRepository",
		},
	}

	for _, d := range testData {
		d := d
		t.Run(d.doc, func(t *testing.T) {
			t.Parallel()
			deviceOptions := []func(*container.TestContainerConfig){container.WithIsolation(d.isolation)}
			for _, deviceName := range d.devices {
				deviceOptions = append(deviceOptions, container.WithWindowsDevice(deviceName))
			}

			id := container.Create(ctx, t, client, deviceOptions...)

			// Hyper-V isolation is failing even with no actual devices added.
			// TODO: Once https://github.com/moby/moby/issues/43395 is resolved,
			// remove this skip.If and validate the expected behaviour under Hyper-V.
			skip.If(t, d.isolation == containertypes.IsolationHyperV && !d.expectedStartFailure, "FIXME. HyperV isolation setup is probably incorrect in the test")

			err := client.ContainerStart(ctx, id, types.ContainerStartOptions{})
			if d.expectedStartFailure {
				assert.ErrorContains(t, err, d.expectedStartFailureMessage)
				return
			}

			assert.NilError(t, err)

			poll.WaitOn(t, container.IsInState(ctx, client, id, "running"), poll.WithDelay(100*time.Millisecond))

			// /Windows/System32/HostDriverStore is mounted from the host when class GUID 5B45201D-F2F2-4F3B-85BB-30FF1F953599
			// is mounted. See `C:\windows\System32\containers\devices.def` on a Windows host for (slightly more) details.
			res, err := container.Exec(ctx, client, id, []string{"sh", "-c",
				"ls -d /Windows/System32/HostDriverStore/* | grep /Windows/System32/HostDriverStore/FileRepository"})
			assert.NilError(t, err)
			assert.Equal(t, d.expectedExitCode, res.ExitCode)
			if d.expectedExitCode == 0 {
				assert.Equal(t, d.expectedStdout, strings.TrimSpace(res.Stdout()))
				assert.Equal(t, d.expectedStderr, strings.TrimSpace(res.Stderr()))
			}

		})
	}
}