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  }