github.com/lazyboychen7/engine@v17.12.1-ce-rc2+incompatible/builder/dockerfile/internals_test.go (about) 1 package dockerfile 2 3 import ( 4 "fmt" 5 "runtime" 6 "testing" 7 8 "github.com/docker/docker/api/types" 9 "github.com/docker/docker/api/types/backend" 10 "github.com/docker/docker/api/types/container" 11 "github.com/docker/docker/builder" 12 "github.com/docker/docker/builder/remotecontext" 13 "github.com/docker/docker/pkg/archive" 14 "github.com/docker/go-connections/nat" 15 "github.com/stretchr/testify/assert" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestEmptyDockerfile(t *testing.T) { 20 contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") 21 defer cleanup() 22 23 createTestTempFile(t, contextDir, builder.DefaultDockerfileName, "", 0777) 24 25 readAndCheckDockerfile(t, "emptyDockerfile", contextDir, "", "the Dockerfile (Dockerfile) cannot be empty") 26 } 27 28 func TestSymlinkDockerfile(t *testing.T) { 29 contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") 30 defer cleanup() 31 32 createTestSymlink(t, contextDir, builder.DefaultDockerfileName, "/etc/passwd") 33 34 // The reason the error is "Cannot locate specified Dockerfile" is because 35 // in the builder, the symlink is resolved within the context, therefore 36 // Dockerfile -> /etc/passwd becomes etc/passwd from the context which is 37 // a nonexistent file. 38 expectedError := fmt.Sprintf("Cannot locate specified Dockerfile: %s", builder.DefaultDockerfileName) 39 40 readAndCheckDockerfile(t, "symlinkDockerfile", contextDir, builder.DefaultDockerfileName, expectedError) 41 } 42 43 func TestDockerfileOutsideTheBuildContext(t *testing.T) { 44 contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") 45 defer cleanup() 46 47 expectedError := "Forbidden path outside the build context: ../../Dockerfile ()" 48 49 readAndCheckDockerfile(t, "DockerfileOutsideTheBuildContext", contextDir, "../../Dockerfile", expectedError) 50 } 51 52 func TestNonExistingDockerfile(t *testing.T) { 53 contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") 54 defer cleanup() 55 56 expectedError := "Cannot locate specified Dockerfile: Dockerfile" 57 58 readAndCheckDockerfile(t, "NonExistingDockerfile", contextDir, "Dockerfile", expectedError) 59 } 60 61 func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath, expectedError string) { 62 tarStream, err := archive.Tar(contextDir, archive.Uncompressed) 63 require.NoError(t, err) 64 65 defer func() { 66 if err = tarStream.Close(); err != nil { 67 t.Fatalf("Error when closing tar stream: %s", err) 68 } 69 }() 70 71 if dockerfilePath == "" { // handled in BuildWithContext 72 dockerfilePath = builder.DefaultDockerfileName 73 } 74 75 config := backend.BuildConfig{ 76 Options: &types.ImageBuildOptions{Dockerfile: dockerfilePath}, 77 Source: tarStream, 78 } 79 _, _, err = remotecontext.Detect(config) 80 assert.EqualError(t, err, expectedError) 81 } 82 83 func TestCopyRunConfig(t *testing.T) { 84 defaultEnv := []string{"foo=1"} 85 defaultCmd := []string{"old"} 86 87 var testcases = []struct { 88 doc string 89 modifiers []runConfigModifier 90 expected *container.Config 91 }{ 92 { 93 doc: "Set the command", 94 modifiers: []runConfigModifier{withCmd([]string{"new"})}, 95 expected: &container.Config{ 96 Cmd: []string{"new"}, 97 Env: defaultEnv, 98 }, 99 }, 100 { 101 doc: "Set the command to a comment", 102 modifiers: []runConfigModifier{withCmdComment("comment", runtime.GOOS)}, 103 expected: &container.Config{ 104 Cmd: append(defaultShellForOS(runtime.GOOS), "#(nop) ", "comment"), 105 Env: defaultEnv, 106 }, 107 }, 108 { 109 doc: "Set the command and env", 110 modifiers: []runConfigModifier{ 111 withCmd([]string{"new"}), 112 withEnv([]string{"one", "two"}), 113 }, 114 expected: &container.Config{ 115 Cmd: []string{"new"}, 116 Env: []string{"one", "two"}, 117 }, 118 }, 119 } 120 121 for _, testcase := range testcases { 122 runConfig := &container.Config{ 123 Cmd: defaultCmd, 124 Env: defaultEnv, 125 } 126 runConfigCopy := copyRunConfig(runConfig, testcase.modifiers...) 127 assert.Equal(t, testcase.expected, runConfigCopy, testcase.doc) 128 // Assert the original was not modified 129 assert.NotEqual(t, runConfig, runConfigCopy, testcase.doc) 130 } 131 132 } 133 134 func fullMutableRunConfig() *container.Config { 135 return &container.Config{ 136 Cmd: []string{"command", "arg1"}, 137 Env: []string{"env1=foo", "env2=bar"}, 138 ExposedPorts: nat.PortSet{ 139 "1000/tcp": {}, 140 "1001/tcp": {}, 141 }, 142 Volumes: map[string]struct{}{ 143 "one": {}, 144 "two": {}, 145 }, 146 Entrypoint: []string{"entry", "arg1"}, 147 OnBuild: []string{"first", "next"}, 148 Labels: map[string]string{ 149 "label1": "value1", 150 "label2": "value2", 151 }, 152 Shell: []string{"shell", "-c"}, 153 } 154 } 155 156 func TestDeepCopyRunConfig(t *testing.T) { 157 runConfig := fullMutableRunConfig() 158 copy := copyRunConfig(runConfig) 159 assert.Equal(t, fullMutableRunConfig(), copy) 160 161 copy.Cmd[1] = "arg2" 162 copy.Env[1] = "env2=new" 163 copy.ExposedPorts["10002"] = struct{}{} 164 copy.Volumes["three"] = struct{}{} 165 copy.Entrypoint[1] = "arg2" 166 copy.OnBuild[0] = "start" 167 copy.Labels["label3"] = "value3" 168 copy.Shell[0] = "sh" 169 assert.Equal(t, fullMutableRunConfig(), runConfig) 170 }