github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/builder/context_test.go (about) 1 package builder 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 "testing" 13 14 "github.com/docker/docker/pkg/archive" 15 ) 16 17 const ( 18 dockerfileTestName = "Dockerfile-test" 19 dockerfileContent = "FROM busybox" 20 ) 21 22 var prepareEmpty = func(t *testing.T) string { 23 return "" 24 } 25 26 var prepareNoFiles = func(t *testing.T) string { 27 contextDir, err := ioutil.TempDir("", "builder-context-test") 28 29 if err != nil { 30 t.Fatalf("Error when creating temporary directory: %s", err) 31 } 32 33 return contextDir 34 } 35 36 var prepareOneFile = func(t *testing.T) string { 37 contextDir, err := ioutil.TempDir("", "builder-context-test") 38 39 if err != nil { 40 t.Fatalf("Error when creating temporary directory: %s", err) 41 } 42 43 dockerfileFilename := filepath.Join(contextDir, dockerfileTestName) 44 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 45 46 if err != nil { 47 t.Fatalf("Error with writing to file: %s", err) 48 } 49 50 return contextDir 51 } 52 53 func testValidateContextDirectory(t *testing.T, prepare func(t *testing.T) string, excludes []string) { 54 contextDir := prepare(t) 55 56 defer os.RemoveAll(contextDir) 57 err := ValidateContextDirectory(contextDir, excludes) 58 59 if err != nil { 60 t.Fatalf("Error should be nil, got: %s", err) 61 } 62 } 63 64 func TestGetContextFromLocalDirNoDockerfile(t *testing.T) { 65 contextDir, err := ioutil.TempDir("", "builder-context-test") 66 67 defer os.RemoveAll(contextDir) 68 69 if err != nil { 70 t.Fatalf("Error with creating temporary directory: %s", err) 71 } 72 73 absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "") 74 75 if err == nil { 76 t.Fatalf("Error should not be nil") 77 } 78 79 if absContextDir != "" { 80 t.Fatalf("Absolute directory path should be empty, got: %s", absContextDir) 81 } 82 83 if relDockerfile != "" { 84 t.Fatalf("Relative path to Dockerfile should be empty, got: %s", relDockerfile) 85 } 86 } 87 88 func TestGetContextFromLocalDirNotExistingDir(t *testing.T) { 89 contextDir, err := ioutil.TempDir("", "builder-context-test") 90 91 if err != nil { 92 t.Fatalf("Error with creating temporary directory: %s", err) 93 } 94 95 defer os.RemoveAll(contextDir) 96 97 fakePath := filepath.Join(contextDir, "fake") 98 99 absContextDir, relDockerfile, err := GetContextFromLocalDir(fakePath, "") 100 101 if err == nil { 102 t.Fatalf("Error should not be nil") 103 } 104 105 if absContextDir != "" { 106 t.Fatalf("Absolute directory path should be empty, got: %s", absContextDir) 107 } 108 109 if relDockerfile != "" { 110 t.Fatalf("Relative path to Dockerfile should be empty, got: %s", relDockerfile) 111 } 112 } 113 114 func TestGetContextFromLocalDirNotExistingDockerfile(t *testing.T) { 115 contextDir, err := ioutil.TempDir("", "builder-context-test") 116 117 if err != nil { 118 t.Fatalf("Error with creating temporary directory: %s", err) 119 } 120 121 defer os.RemoveAll(contextDir) 122 123 fakePath := filepath.Join(contextDir, "fake") 124 125 absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, fakePath) 126 127 if err == nil { 128 t.Fatalf("Error should not be nil") 129 } 130 131 if absContextDir != "" { 132 t.Fatalf("Absolute directory path should be empty, got: %s", absContextDir) 133 } 134 135 if relDockerfile != "" { 136 t.Fatalf("Relative path to Dockerfile should be empty, got: %s", relDockerfile) 137 } 138 } 139 140 func TestGetContextFromLocalDirWithNoDirectory(t *testing.T) { 141 contextDir, err := ioutil.TempDir("", "builder-context-test") 142 143 if err != nil { 144 t.Fatalf("Error with creating temporary directory: %s", err) 145 } 146 147 defer os.RemoveAll(contextDir) 148 149 dockerfileFilename := filepath.Join(contextDir, DefaultDockerfileName) 150 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 151 152 if err != nil { 153 t.Fatalf("Error when writing file (%s) contents: %s", dockerfileFilename, err) 154 } 155 156 workingDirectory, err := os.Getwd() 157 158 if err != nil { 159 t.Fatalf("Error when retrieving working directory: %s", err) 160 } 161 162 defer os.Chdir(workingDirectory) 163 164 err = os.Chdir(contextDir) 165 166 if err != nil { 167 t.Fatalf("Error when changing directory to %s: %s", contextDir, err) 168 } 169 absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "") 170 171 if err != nil { 172 t.Fatalf("Error when getting context from local dir: %s", err) 173 } 174 175 if absContextDir != contextDir { 176 t.Fatalf("Absolute directory path should be equal to %s, got: %s", contextDir, absContextDir) 177 } 178 179 if relDockerfile != DefaultDockerfileName { 180 t.Fatalf("Relative path to dockerfile should be equal to %s, got: %s", DefaultDockerfileName, relDockerfile) 181 } 182 } 183 184 func TestGetContextFromLocalDirWithDockerfile(t *testing.T) { 185 contextDir, err := ioutil.TempDir("", "builder-context-test") 186 187 if err != nil { 188 t.Fatalf("Error with creating temporary directory: %s", err) 189 } 190 191 defer os.RemoveAll(contextDir) 192 193 dockerfileFilename := filepath.Join(contextDir, DefaultDockerfileName) 194 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 195 196 if err != nil { 197 t.Fatalf("Error when writing file (%s) contents: %s", dockerfileFilename, err) 198 } 199 200 absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, "") 201 202 if err != nil { 203 t.Fatalf("Error when getting context from local dir: %s", err) 204 } 205 206 if absContextDir != contextDir { 207 t.Fatalf("Absolute directory path should be equal to %s, got: %s", contextDir, absContextDir) 208 } 209 210 if relDockerfile != DefaultDockerfileName { 211 t.Fatalf("Relative path to dockerfile should be equal to %s, got: %s", DefaultDockerfileName, relDockerfile) 212 } 213 } 214 215 func TestGetContextFromLocalDirLocalFile(t *testing.T) { 216 contextDir, err := ioutil.TempDir("", "builder-context-test") 217 218 if err != nil { 219 t.Fatalf("Error with creating temporary directory: %s", err) 220 } 221 222 defer os.RemoveAll(contextDir) 223 224 dockerfileFilename := filepath.Join(contextDir, DefaultDockerfileName) 225 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 226 227 if err != nil { 228 t.Fatalf("Error when writing file (%s) contents: %s", dockerfileFilename, err) 229 } 230 231 testFilename := filepath.Join(contextDir, "tmpTest") 232 testContent := "test" 233 err = ioutil.WriteFile(testFilename, []byte(testContent), 0777) 234 235 if err != nil { 236 t.Fatalf("Error when writing file (%s) contents: %s", testFilename, err) 237 } 238 239 absContextDir, relDockerfile, err := GetContextFromLocalDir(testFilename, "") 240 241 if err == nil { 242 t.Fatalf("Error should not be nil") 243 } 244 245 if absContextDir != "" { 246 t.Fatalf("Absolute directory path should be empty, got: %s", absContextDir) 247 } 248 249 if relDockerfile != "" { 250 t.Fatalf("Relative path to Dockerfile should be empty, got: %s", relDockerfile) 251 } 252 } 253 254 func TestGetContextFromLocalDirWithCustomDockerfile(t *testing.T) { 255 contextDir, err := ioutil.TempDir("", "builder-context-test") 256 257 if err != nil { 258 t.Fatalf("Error with creating temporary directory: %s", err) 259 } 260 261 defer os.RemoveAll(contextDir) 262 263 workingDirectory, err := os.Getwd() 264 265 if err != nil { 266 t.Fatalf("Error when retrieving working directory: %s", err) 267 } 268 269 defer os.Chdir(workingDirectory) 270 271 err = os.Chdir(contextDir) 272 273 if err != nil { 274 t.Fatalf("Error when changing directory to %s: %s", contextDir, err) 275 } 276 277 dockerfileFilename := filepath.Join(contextDir, dockerfileTestName) 278 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 279 280 if err != nil { 281 t.Fatalf("Error when writing file (%s) contents: %s", dockerfileFilename, err) 282 } 283 284 absContextDir, relDockerfile, err := GetContextFromLocalDir(contextDir, dockerfileTestName) 285 286 if err != nil { 287 t.Fatalf("Error when getting context from local dir: %s", err) 288 } 289 290 if absContextDir != contextDir { 291 t.Fatalf("Absolute directory path should be equal to %s, got: %s", contextDir, absContextDir) 292 } 293 294 if relDockerfile != dockerfileTestName { 295 t.Fatalf("Relative path to dockerfile should be equal to %s, got: %s", dockerfileTestName, relDockerfile) 296 } 297 298 } 299 300 func TestGetContextFromReaderString(t *testing.T) { 301 tarArchive, relDockerfile, err := GetContextFromReader(ioutil.NopCloser(strings.NewReader(dockerfileContent)), "") 302 303 if err != nil { 304 t.Fatalf("Error when executing GetContextFromReader: %s", err) 305 } 306 307 tarReader := tar.NewReader(tarArchive) 308 309 _, err = tarReader.Next() 310 311 if err != nil { 312 t.Fatalf("Error when reading tar archive: %s", err) 313 } 314 315 buff := new(bytes.Buffer) 316 buff.ReadFrom(tarReader) 317 contents := buff.String() 318 319 _, err = tarReader.Next() 320 321 if err != io.EOF { 322 t.Fatalf("Tar stream too long: %s", err) 323 } 324 325 if err = tarArchive.Close(); err != nil { 326 t.Fatalf("Error when closing tar stream: %s", err) 327 } 328 329 if dockerfileContent != contents { 330 t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContent, contents) 331 } 332 333 if relDockerfile != DefaultDockerfileName { 334 t.Fatalf("Relative path not equals %s, got: %s", DefaultDockerfileName, relDockerfile) 335 } 336 } 337 338 func TestGetContextFromReaderTar(t *testing.T) { 339 contextDir, err := ioutil.TempDir("", "builder-context-test") 340 341 if err != nil { 342 t.Fatalf("Error with creating temporary directory: %s", err) 343 } 344 345 defer os.RemoveAll(contextDir) 346 347 dockerfileFilename := filepath.Join(contextDir, dockerfileTestName) 348 err = ioutil.WriteFile(dockerfileFilename, []byte(dockerfileContent), 0777) 349 350 if err != nil { 351 t.Fatalf("Error when writing file (%s) contents: %s", dockerfileFilename, err) 352 } 353 354 tarStream, err := archive.Tar(contextDir, archive.Uncompressed) 355 356 if err != nil { 357 t.Fatalf("Error when creating tar: %s", err) 358 } 359 360 tarArchive, relDockerfile, err := GetContextFromReader(tarStream, dockerfileTestName) 361 362 if err != nil { 363 t.Fatalf("Error when executing GetContextFromReader: %s", err) 364 } 365 366 tarReader := tar.NewReader(tarArchive) 367 368 header, err := tarReader.Next() 369 370 if err != nil { 371 t.Fatalf("Error when reading tar archive: %s", err) 372 } 373 374 if header.Name != dockerfileTestName { 375 t.Fatalf("Dockerfile name should be: %s, got: %s", dockerfileTestName, header.Name) 376 } 377 378 buff := new(bytes.Buffer) 379 buff.ReadFrom(tarReader) 380 contents := buff.String() 381 382 _, err = tarReader.Next() 383 384 if err != io.EOF { 385 t.Fatalf("Tar stream too long: %s", err) 386 } 387 388 if err = tarArchive.Close(); err != nil { 389 t.Fatalf("Error when closing tar stream: %s", err) 390 } 391 392 if dockerfileContent != contents { 393 t.Fatalf("Uncompressed tar archive does not equal: %s, got: %s", dockerfileContent, contents) 394 } 395 396 if relDockerfile != dockerfileTestName { 397 t.Fatalf("Relative path not equals %s, got: %s", dockerfileTestName, relDockerfile) 398 } 399 } 400 401 func TestValidateContextDirectoryEmptyContext(t *testing.T) { 402 // This isn't a valid test on Windows. See https://play.golang.org/p/RR6z6jxR81. 403 // The test will ultimately end up calling filepath.Abs(""). On Windows, 404 // golang will error. On Linux, golang will return /. Due to there being 405 // drive letters on Windows, this is probably the correct behaviour for 406 // Windows. 407 if runtime.GOOS == "windows" { 408 t.Skip("Invalid test on Windows") 409 } 410 testValidateContextDirectory(t, prepareEmpty, []string{}) 411 } 412 413 func TestValidateContextDirectoryContextWithNoFiles(t *testing.T) { 414 testValidateContextDirectory(t, prepareNoFiles, []string{}) 415 } 416 417 func TestValidateContextDirectoryWithOneFile(t *testing.T) { 418 testValidateContextDirectory(t, prepareOneFile, []string{}) 419 } 420 421 func TestValidateContextDirectoryWithOneFileExcludes(t *testing.T) { 422 testValidateContextDirectory(t, prepareOneFile, []string{dockerfileTestName}) 423 }