github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/container_run_mount_windows_test.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "fmt" 21 "os" 22 "testing" 23 24 "github.com/containerd/nerdctl/pkg/inspecttypes/dockercompat" 25 "github.com/containerd/nerdctl/pkg/testutil" 26 "gotest.tools/v3/assert" 27 ) 28 29 func TestRunMountVolume(t *testing.T) { 30 t.Parallel() 31 base := testutil.NewBase(t) 32 tID := testutil.Identifier(t) 33 rwDir, err := os.MkdirTemp(t.TempDir(), "rw") 34 if err != nil { 35 t.Fatal(err) 36 } 37 roDir, err := os.MkdirTemp(t.TempDir(), "ro") 38 if err != nil { 39 t.Fatal(err) 40 } 41 rwVolName := tID + "-rw" 42 roVolName := tID + "-ro" 43 for _, v := range []string{rwVolName, roVolName} { 44 defer base.Cmd("volume", "rm", "-f", v).Run() 45 base.Cmd("volume", "create", v).AssertOK() 46 } 47 48 containerName := tID 49 defer base.Cmd("rm", "-f", containerName).AssertOK() 50 base.Cmd("run", 51 "-d", 52 "--name", containerName, 53 "-v", fmt.Sprintf("%s:C:/mnt1", rwDir), 54 "-v", fmt.Sprintf("%s:C:/mnt2:ro", roDir), 55 "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), 56 "-v", fmt.Sprintf("%s:C:/mnt4:ro", roVolName), 57 testutil.CommonImage, 58 "ping localhost -t", 59 ).AssertOK() 60 61 base.Cmd("exec", containerName, "cmd", "/c", "echo -n str1 > C:/mnt1/file1").AssertOK() 62 base.Cmd("exec", containerName, "cmd", "/c", "echo -n str2 > C:/mnt2/file2").AssertFail() 63 base.Cmd("exec", containerName, "cmd", "/c", "echo -n str3 > C:/mnt3/file3").AssertOK() 64 base.Cmd("exec", containerName, "cmd", "/c", "echo -n str4 > C:/mnt4/file4").AssertFail() 65 base.Cmd("rm", "-f", containerName).AssertOK() 66 67 base.Cmd("run", 68 "--rm", 69 "-v", fmt.Sprintf("%s:C:/mnt1", rwDir), 70 "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), 71 testutil.CommonImage, 72 "cat", "C:/mnt1/file1", "C:/mnt3/file3", 73 ).AssertOutContainsAll("str1", "str3") 74 base.Cmd("run", 75 "--rm", 76 "-v", fmt.Sprintf("%s:C:/mnt3/mnt1", rwDir), 77 "-v", fmt.Sprintf("%s:C:/mnt3", rwVolName), 78 testutil.CommonImage, 79 "cat", "C:/mnt3/mnt1/file1", "C:/mnt3/file3", 80 ).AssertOutContainsAll("str1", "str3") 81 } 82 83 func TestRunMountVolumeInspect(t *testing.T) { 84 base := testutil.NewBase(t) 85 testContainer := testutil.Identifier(t) 86 testVolume := testutil.Identifier(t) 87 88 defer base.Cmd("volume", "rm", "-f", testVolume).Run() 89 base.Cmd("volume", "create", testVolume).AssertOK() 90 inspectVolume := base.InspectVolume(testVolume) 91 namedVolumeSource := inspectVolume.Mountpoint 92 93 base.Cmd( 94 "run", "-d", "--name", testContainer, 95 "-v", "C:/mnt1", 96 "-v", "C:/mnt2:C:/mnt2", 97 "-v", "\\\\.\\pipe\\containerd-containerd:\\\\.\\pipe\\containerd-containerd", 98 "-v", fmt.Sprintf("%s:C:/mnt3", testVolume), 99 testutil.CommonImage, 100 ).AssertOK() 101 102 inspect := base.InspectContainer(testContainer) 103 // convert array to map to get by key of Destination 104 actual := make(map[string]dockercompat.MountPoint) 105 for i := range inspect.Mounts { 106 actual[inspect.Mounts[i].Destination] = inspect.Mounts[i] 107 } 108 109 expected := []struct { 110 dest string 111 mountPoint dockercompat.MountPoint 112 }{ 113 // anonymous volume 114 { 115 dest: "C:\\mnt1", 116 mountPoint: dockercompat.MountPoint{ 117 Type: "volume", 118 Source: "", // source of anonymous volume is a generated path, so here will not check it. 119 Destination: "C:\\mnt1", 120 }, 121 }, 122 123 // bind 124 { 125 dest: "C:\\mnt2", 126 mountPoint: dockercompat.MountPoint{ 127 Type: "bind", 128 Source: "C:\\mnt2", 129 Destination: "C:\\mnt2", 130 }, 131 }, 132 133 // named pipe 134 { 135 dest: "\\\\.\\pipe\\containerd-containerd", 136 mountPoint: dockercompat.MountPoint{ 137 Type: "npipe", 138 Source: "\\\\.\\pipe\\containerd-containerd", 139 Destination: "\\\\.\\pipe\\containerd-containerd", 140 }, 141 }, 142 143 // named volume 144 { 145 dest: "C:\\mnt3", 146 mountPoint: dockercompat.MountPoint{ 147 Type: "volume", 148 Name: testVolume, 149 Source: namedVolumeSource, 150 Destination: "C:\\mnt3", 151 }, 152 }, 153 } 154 155 for i := range expected { 156 testCase := expected[i] 157 t.Logf("test volume[dest=%q]", testCase.dest) 158 159 mountPoint, ok := actual[testCase.dest] 160 assert.Assert(base.T, ok) 161 162 assert.Equal(base.T, testCase.mountPoint.Type, mountPoint.Type) 163 assert.Equal(base.T, testCase.mountPoint.Destination, mountPoint.Destination) 164 165 if testCase.mountPoint.Source == "" { 166 // for anonymous volumes, we want to make sure that the source is not the same as the destination 167 assert.Assert(base.T, mountPoint.Source != testCase.mountPoint.Destination) 168 } else { 169 assert.Equal(base.T, testCase.mountPoint.Source, mountPoint.Source) 170 } 171 172 if testCase.mountPoint.Name != "" { 173 assert.Equal(base.T, testCase.mountPoint.Name, mountPoint.Name) 174 } 175 } 176 } 177 178 func TestRunMountAnonymousVolume(t *testing.T) { 179 t.Parallel() 180 base := testutil.NewBase(t) 181 base.Cmd("run", "--rm", "-v", "TestVolume:C:/mnt", testutil.CommonImage).AssertOK() 182 183 // For docker-campatibility, Unrecognised volume spec: invalid volume specification: 'TestVolume' 184 base.Cmd("run", "--rm", "-v", "TestVolume", testutil.CommonImage).AssertFail() 185 186 // Destination must be an absolute path not named volume 187 base.Cmd("run", "--rm", "-v", "TestVolume2:TestVolumes", testutil.CommonImage).AssertFail() 188 } 189 190 func TestRunMountRelativePath(t *testing.T) { 191 t.Parallel() 192 base := testutil.NewBase(t) 193 base.Cmd("run", "--rm", "-v", "./mnt:C:/mnt1", testutil.CommonImage, "cmd").AssertOK() 194 195 // Destination cannot be a relative path 196 base.Cmd("run", "--rm", "-v", "./mnt", testutil.CommonImage).AssertFail() 197 base.Cmd("run", "--rm", "-v", "./mnt:./mnt1", testutil.CommonImage, "cmd").AssertFail() 198 } 199 200 func TestRunMountNamedPipeVolume(t *testing.T) { 201 t.Parallel() 202 base := testutil.NewBase(t) 203 base.Cmd("run", "--rm", "-v", `\\.\pipe\containerd-containerd`, testutil.CommonImage).AssertFail() 204 } 205 206 func TestRunMountVolumeSpec(t *testing.T) { 207 t.Parallel() 208 base := testutil.NewBase(t) 209 base.Cmd("run", "--rm", "-v", `InvalidPathC:\TestVolume:C:\Mount`, testutil.CommonImage).AssertFail() 210 base.Cmd("run", "--rm", "-v", `C:\TestVolume:C:\Mount:ro,rw:boot`, testutil.CommonImage).AssertFail() 211 212 // If -v is an empty string, it will be ignored 213 base.Cmd("run", "--rm", "-v", "", testutil.CommonImage).AssertOK() 214 }