github.com/tri-adam/singularity@v3.1.1+incompatible/cmd/singularity/docker_test.go (about) 1 // Copyright (c) 2018, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package main 7 8 import ( 9 "fmt" 10 "os" 11 "os/exec" 12 "path" 13 "strings" 14 "testing" 15 16 "github.com/sylabs/singularity/internal/pkg/test" 17 "golang.org/x/sys/unix" 18 ) 19 20 func TestDocker(t *testing.T) { 21 tests := []struct { 22 name string 23 imagePath string 24 expectSuccess bool 25 }{ 26 {"BusyBox", "docker://busybox", true}, 27 {"DoesNotExist", "docker://something_that_doesnt_exist_ever", false}, 28 } 29 30 for _, tt := range tests { 31 t.Run(tt.name, test.WithPrivilege(func(t *testing.T) { 32 imagePath := path.Join(testDir, "container") 33 defer os.Remove(imagePath) 34 35 b, err := imageBuild(buildOpts{}, imagePath, tt.imagePath) 36 if tt.expectSuccess { 37 if err != nil { 38 t.Log(string(b)) 39 t.Fatalf("unexpected failure: %v", err) 40 } 41 imageVerify(t, imagePath, false) 42 } else if !tt.expectSuccess && err == nil { 43 t.Log(string(b)) 44 t.Fatal("unexpected success") 45 } 46 })) 47 } 48 } 49 50 // AUFS sanity tests 51 func TestDockerAUFS(t *testing.T) { 52 test.EnsurePrivilege(t) 53 54 imagePath := path.Join(testDir, "container") 55 defer os.Remove(imagePath) 56 57 b, err := imageBuild(buildOpts{}, imagePath, "docker://dctrud/docker-aufs-sanity") 58 if err != nil { 59 t.Log(string(b)) 60 t.Fatalf("unexpected failure: %v", err) 61 } 62 63 fileTests := []struct { 64 name string 65 execArgs []string 66 expectSuccess bool 67 }{ 68 {"File2", []string{"ls", "/test/whiteout-dir/file2", "/test/whiteout-file/file2", "/test/normal-dir/file2"}, true}, 69 {"File1", []string{"ls", "/test/whiteout-dir/file1", "/test/whiteout-file/file1"}, false}, 70 {"Glob", []string{"ls", "/test/*/.wh*"}, false}, 71 } 72 for _, tt := range fileTests { 73 t.Run(tt.name, test.WithoutPrivilege(func(t *testing.T) { 74 _, stderr, exitCode, err := imageExec(t, "exec", opts{}, imagePath, tt.execArgs) 75 if tt.expectSuccess && (exitCode != 0) { 76 t.Log(stderr) 77 t.Fatalf("unexpected failure running '%v': %v", strings.Join(tt.execArgs, " "), err) 78 } else if !tt.expectSuccess && (exitCode != 1) { 79 t.Log(stderr) 80 t.Fatalf("unexpected success running '%v'", strings.Join(tt.execArgs, " ")) 81 } 82 })) 83 } 84 } 85 86 // Check force permissions for user builds #977 87 func TestDockerPermissions(t *testing.T) { 88 test.DropPrivilege(t) 89 defer test.ResetPrivilege(t) 90 91 imagePath := path.Join(testDir, "container") 92 defer os.Remove(imagePath) 93 94 b, err := imageBuild(buildOpts{}, imagePath, "docker://dctrud/docker-singularity-userperms") 95 if err != nil { 96 t.Log(string(b)) 97 t.Fatalf("unexpected failure: %v", err) 98 } 99 100 fileTests := []struct { 101 name string 102 execArgs []string 103 expectSuccess bool 104 }{ 105 {"TestDir", []string{"ls", "/testdir/"}, true}, 106 {"TestDirFile", []string{"ls", "/testdir/testfile"}, false}, 107 } 108 for _, tt := range fileTests { 109 t.Run(tt.name, test.WithoutPrivilege(func(t *testing.T) { 110 _, stderr, exitCode, err := imageExec(t, "exec", opts{}, imagePath, tt.execArgs) 111 if tt.expectSuccess && (exitCode != 0) { 112 t.Log(stderr) 113 t.Fatalf("unexpected failure running '%v': %v", strings.Join(tt.execArgs, " "), err) 114 } else if !tt.expectSuccess && (exitCode != 1) { 115 t.Log(stderr) 116 t.Fatalf("unexpected success running '%v'", strings.Join(tt.execArgs, " ")) 117 } 118 })) 119 } 120 } 121 122 // Check whiteout of symbolic links #1592 #1576 123 func TestDockerWhiteoutSymlink(t *testing.T) { 124 test.DropPrivilege(t) 125 defer test.ResetPrivilege(t) 126 127 imagePath := path.Join(testDir, "container") 128 defer os.Remove(imagePath) 129 130 b, err := imageBuild(buildOpts{}, imagePath, "docker://dctrud/docker-singularity-linkwh") 131 if err != nil { 132 t.Log(string(b)) 133 t.Fatalf("unexpected failure: %v", err) 134 } 135 imageVerify(t, imagePath, false) 136 } 137 138 func getKernelMajor(t *testing.T) (major int) { 139 var buf unix.Utsname 140 if err := unix.Uname(&buf); err != nil { 141 t.Fatalf("uname failed: %v", err) 142 } 143 n, err := fmt.Sscanf(string(buf.Release[:]), "%d.", &major) 144 if n != 1 || err != nil { 145 t.Fatalf("Sscanf failed: %v %v", n, err) 146 } 147 return 148 } 149 150 func TestDockerDefFile(t *testing.T) { 151 tests := []struct { 152 name string 153 kernelMajorRequired int 154 from string 155 }{ 156 {"Arch", 3, "dock0/arch:latest"}, 157 {"BusyBox", 0, "busybox:latest"}, 158 {"CentOS", 0, "centos:latest"}, 159 {"Ubuntu", 0, "ubuntu:16.04"}, 160 } 161 162 for _, tt := range tests { 163 t.Run(tt.name, test.WithPrivilege(func(t *testing.T) { 164 if getKernelMajor(t) < tt.kernelMajorRequired { 165 t.Skipf("kernel >=%v.x required", tt.kernelMajorRequired) 166 } 167 168 imagePath := path.Join(testDir, "container") 169 defer os.Remove(imagePath) 170 171 deffile := prepareDefFile(DefFileDetail{ 172 Bootstrap: "docker", 173 From: tt.from, 174 }) 175 defer os.Remove(deffile) 176 177 if b, err := imageBuild(buildOpts{}, imagePath, deffile); err != nil { 178 t.Log(string(b)) 179 t.Fatalf("unexpected failure: %v", err) 180 } 181 imageVerify(t, imagePath, false) 182 })) 183 } 184 } 185 186 func prepRegistry(t *testing.T) { 187 commands := [][]string{ 188 {"run", "-d", "-p", "5000:5000", "--restart=always", "--name", "registry", "registry:2"}, 189 {"pull", "busybox"}, 190 {"tag", "busybox", "localhost:5000/my-busybox"}, 191 {"push", "localhost:5000/my-busybox"}, 192 } 193 194 for _, command := range commands { 195 cmd := exec.Command("docker", command...) 196 if b, err := cmd.CombinedOutput(); err != nil { 197 t.Logf(string(b)) 198 t.Fatalf("command failed: %v", strings.Join(command, " ")) 199 } 200 } 201 } 202 203 func killRegistry(t *testing.T) { 204 commands := [][]string{ 205 {"kill", "registry"}, 206 {"rm", "registry"}, 207 } 208 209 for _, command := range commands { 210 cmd := exec.Command("docker", command...) 211 if b, err := cmd.CombinedOutput(); err != nil { 212 t.Logf(string(b)) 213 t.Fatalf("command failed: %v", strings.Join(command, " ")) 214 } 215 } 216 } 217 218 func TestDockerRegistry(t *testing.T) { 219 test.EnsurePrivilege(t) 220 221 if _, err := exec.LookPath("docker"); err != nil { 222 t.Skip("docker not installed") 223 } 224 225 prepRegistry(t) 226 defer killRegistry(t) 227 228 tests := []struct { 229 name string 230 expectSuccess bool 231 dfd DefFileDetail 232 }{ 233 {"BusyBox", true, DefFileDetail{ 234 Bootstrap: "docker", 235 From: "localhost:5000/my-busybox", 236 }}, 237 {"BusyBoxRegistry", true, DefFileDetail{ 238 Bootstrap: "docker", 239 From: "my-busybox", 240 Registry: "localhost:5000", 241 }}, 242 {"BusyBoxNamespace", false, DefFileDetail{ 243 Bootstrap: "docker", 244 From: "my-busybox", 245 Registry: "localhost:5000", 246 Namespace: "not-a-namespace", 247 }}, 248 } 249 250 for _, tt := range tests { 251 t.Run(tt.name, test.WithPrivilege(func(t *testing.T) { 252 opts := buildOpts{ 253 env: append(os.Environ(), "SINGULARITY_NOHTTPS=true"), 254 } 255 imagePath := path.Join(testDir, "container") 256 defer os.Remove(imagePath) 257 258 defFile := prepareDefFile(tt.dfd) 259 260 b, err := imageBuild(opts, imagePath, defFile) 261 if tt.expectSuccess { 262 if err != nil { 263 t.Log(string(b)) 264 t.Fatalf("unexpected failure: %v", err) 265 } 266 imageVerify(t, imagePath, false) 267 } else if !tt.expectSuccess && (err == nil) { 268 t.Log(string(b)) 269 t.Fatalf("unexpected success") 270 } 271 })) 272 } 273 }