github.com/stevenmatthewt/agent@v3.5.4+incompatible/bootstrap/integration/docker_integration_test.go (about) 1 package integration 2 3 import ( 4 "runtime" 5 "testing" 6 7 "github.com/buildkite/bintest" 8 ) 9 10 func argumentForCommand(cmd string) interface{} { 11 // This is unpleasant, but we have to work around the fact that we generate 12 // batch scripts for windows and plain commands for everything else 13 if runtime.GOOS == `windows` { 14 return bintest.MatchPattern(`buildkite-script-.+.bat$`) 15 } 16 return cmd 17 } 18 19 func TestRunningCommandWithDocker(t *testing.T) { 20 tester, err := NewBootstrapTester() 21 if err != nil { 22 t.Fatal(err) 23 } 24 defer tester.Close() 25 26 // Mock out the meta-data calls to the agent after checkout 27 agent := tester.MustMock(t, "buildkite-agent") 28 agent. 29 Expect("meta-data", "exists", "buildkite:git:commit"). 30 AndExitWith(0) 31 32 env := []string{ 33 "BUILDKITE_DOCKER=llamas", 34 } 35 36 jobId := "1111-1111-1111-1111" 37 imageId := "buildkite_" + jobId + "_image" 38 containerId := "buildkite_" + jobId + "_container" 39 40 docker := tester.MustMock(t, "docker") 41 docker.ExpectAll([][]interface{}{ 42 {"build", "-f", "Dockerfile", "-t", imageId, "."}, 43 {"run", "--name", containerId, imageId, argumentForCommand("true")}, 44 {"rm", "-f", "-v", containerId}, 45 }) 46 47 expectCommandHooks("0", t, tester) 48 49 tester.RunAndCheck(t, env...) 50 } 51 52 func TestRunningCommandWithDockerAndCustomDockerfile(t *testing.T) { 53 tester, err := NewBootstrapTester() 54 if err != nil { 55 t.Fatal(err) 56 } 57 defer tester.Close() 58 59 // Mock out the meta-data calls to the agent after checkout 60 agent := tester.MustMock(t, "buildkite-agent") 61 agent. 62 Expect("meta-data", "exists", "buildkite:git:commit"). 63 AndExitWith(0) 64 65 env := []string{ 66 "BUILDKITE_DOCKER=llamas", 67 "BUILDKITE_DOCKER_FILE=Dockerfile.llamas", 68 } 69 70 jobId := "1111-1111-1111-1111" 71 imageId := "buildkite_" + jobId + "_image" 72 containerId := "buildkite_" + jobId + "_container" 73 74 docker := tester.MustMock(t, "docker") 75 docker.ExpectAll([][]interface{}{ 76 {"build", "-f", "Dockerfile.llamas", "-t", imageId, "."}, 77 {"run", "--name", containerId, imageId, argumentForCommand("true")}, 78 {"rm", "-f", "-v", containerId}, 79 }) 80 81 expectCommandHooks("0", t, tester) 82 83 tester.RunAndCheck(t, env...) 84 } 85 86 func TestRunningFailingCommandWithDocker(t *testing.T) { 87 tester, err := NewBootstrapTester() 88 if err != nil { 89 t.Fatal(err) 90 } 91 defer tester.Close() 92 93 // Mock out the meta-data calls to the agent after checkout 94 agent := tester.MustMock(t, "buildkite-agent") 95 agent. 96 Expect("meta-data", "exists", "buildkite:git:commit"). 97 AndExitWith(0) 98 99 env := []string{ 100 "BUILDKITE_DOCKER=llamas", 101 } 102 103 jobId := "1111-1111-1111-1111" 104 imageId := "buildkite_" + jobId + "_image" 105 containerId := "buildkite_" + jobId + "_container" 106 107 docker := tester.MustMock(t, "docker") 108 docker.ExpectAll([][]interface{}{ 109 {"build", "-f", "Dockerfile", "-t", imageId, "."}, 110 {"rm", "-f", "-v", containerId}, 111 }) 112 113 docker.Expect("run", "--name", containerId, imageId, argumentForCommand("true")). 114 AndExitWith(1) 115 116 expectCommandHooks("1", t, tester) 117 118 if err = tester.Run(t, env...); err == nil { 119 t.Fatal("Expected bootstrap to fail") 120 } 121 122 tester.CheckMocks(t) 123 } 124 125 func TestRunningCommandWithDockerCompose(t *testing.T) { 126 tester, err := NewBootstrapTester() 127 if err != nil { 128 t.Fatal(err) 129 } 130 defer tester.Close() 131 132 // Mock out the meta-data calls to the agent after checkout 133 agent := tester.MustMock(t, "buildkite-agent") 134 agent. 135 Expect("meta-data", "exists", "buildkite:git:commit"). 136 AndExitWith(0) 137 138 env := []string{ 139 "BUILDKITE_DOCKER_COMPOSE_CONTAINER=llamas", 140 } 141 142 projectName := "buildkite1111111111111111" 143 144 dockerCompose := tester.MustMock(t, "docker-compose") 145 dockerCompose.ExpectAll([][]interface{}{ 146 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "build", "--pull", "llamas"}, 147 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "run", "llamas", argumentForCommand("true")}, 148 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "kill"}, 149 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "rm", "--force", "--all", "-v"}, 150 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "down"}, 151 }) 152 153 expectCommandHooks("0", t, tester) 154 155 tester.RunAndCheck(t, env...) 156 } 157 158 func TestRunningFailingCommandWithDockerCompose(t *testing.T) { 159 tester, err := NewBootstrapTester() 160 if err != nil { 161 t.Fatal(err) 162 } 163 defer tester.Close() 164 165 // Mock out the meta-data calls to the agent after checkout 166 agent := tester.MustMock(t, "buildkite-agent") 167 agent. 168 Expect("meta-data", "exists", "buildkite:git:commit"). 169 AndExitWith(0) 170 171 env := []string{ 172 "BUILDKITE_DOCKER_COMPOSE_CONTAINER=llamas", 173 } 174 175 projectName := "buildkite1111111111111111" 176 177 dockerCompose := tester.MustMock(t, "docker-compose") 178 dockerCompose.ExpectAll([][]interface{}{ 179 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "build", "--pull", "llamas"}, 180 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "kill"}, 181 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "rm", "--force", "--all", "-v"}, 182 {"-f", "docker-compose.yml", "-p", projectName, "--verbose", "down"}, 183 }) 184 185 dockerCompose.Expect("-f", "docker-compose.yml", "-p", projectName, "--verbose", "run", "llamas", argumentForCommand("true")). 186 AndWriteToStderr("Nope!"). 187 AndExitWith(1) 188 189 expectCommandHooks("1", t, tester) 190 191 if err = tester.Run(t, env...); err == nil { 192 t.Fatal("Expected bootstrap to fail") 193 } 194 195 tester.CheckMocks(t) 196 } 197 198 func TestRunningCommandWithDockerComposeAndExtraConfig(t *testing.T) { 199 tester, err := NewBootstrapTester() 200 if err != nil { 201 t.Fatal(err) 202 } 203 defer tester.Close() 204 205 // Mock out the meta-data calls to the agent after checkout 206 agent := tester.MustMock(t, "buildkite-agent") 207 agent. 208 Expect("meta-data", "exists", "buildkite:git:commit"). 209 AndExitWith(0) 210 211 env := []string{ 212 "BUILDKITE_DOCKER_COMPOSE_CONTAINER=llamas", 213 "BUILDKITE_DOCKER_COMPOSE_FILE=dc1.yml:dc2.yml:dc3.yml", 214 } 215 216 projectName := "buildkite1111111111111111" 217 218 dockerCompose := tester.MustMock(t, "docker-compose") 219 dockerCompose.ExpectAll([][]interface{}{ 220 {"-f", "dc1.yml", "-f", "dc2.yml", "-f", "dc3.yml", "-p", projectName, "--verbose", "build", "--pull", "llamas"}, 221 {"-f", "dc1.yml", "-f", "dc2.yml", "-f", "dc3.yml", "-p", projectName, "--verbose", "run", "llamas", argumentForCommand("true")}, 222 {"-f", "dc1.yml", "-f", "dc2.yml", "-f", "dc3.yml", "-p", projectName, "--verbose", "kill"}, 223 {"-f", "dc1.yml", "-f", "dc2.yml", "-f", "dc3.yml", "-p", projectName, "--verbose", "rm", "--force", "--all", "-v"}, 224 {"-f", "dc1.yml", "-f", "dc2.yml", "-f", "dc3.yml", "-p", projectName, "--verbose", "down"}, 225 }) 226 227 expectCommandHooks("0", t, tester) 228 229 tester.RunAndCheck(t, env...) 230 } 231 232 func TestRunningCommandWithDockerComposeAndBuildAll(t *testing.T) { 233 tester, err := NewBootstrapTester() 234 if err != nil { 235 t.Fatal(err) 236 } 237 defer tester.Close() 238 239 // Mock out the meta-data calls to the agent after checkout 240 agent := tester.MustMock(t, "buildkite-agent") 241 agent. 242 Expect("meta-data", "exists", "buildkite:git:commit"). 243 AndExitWith(0) 244 245 env := []string{ 246 "BUILDKITE_DOCKER_COMPOSE_CONTAINER=llamas", 247 "BUILDKITE_DOCKER_COMPOSE_BUILD_ALL=true", 248 } 249 250 dockerCompose := tester.MustMock(t, "docker-compose") 251 dockerCompose.IgnoreUnexpectedInvocations() 252 dockerCompose.Expect("-f", "docker-compose.yml", "-p", "buildkite1111111111111111", "--verbose", "build", "--pull").Once() 253 254 tester.RunAndCheck(t, env...) 255 } 256 257 func expectCommandHooks(exitStatus string, t *testing.T, tester *BootstrapTester) { 258 tester.ExpectGlobalHook("pre-command").Once() 259 tester.ExpectLocalHook("pre-command").Once() 260 tester.ExpectGlobalHook("post-command").Once() 261 tester.ExpectLocalHook("post-command").Once() 262 263 preExitFunc := func(c *bintest.Call) { 264 cmdExitStatus := c.GetEnv(`BUILDKITE_COMMAND_EXIT_STATUS`) 265 if cmdExitStatus != exitStatus { 266 t.Errorf("Expected an exit status of %s, got %v", exitStatus, cmdExitStatus) 267 } 268 c.Exit(0) 269 } 270 271 tester.ExpectGlobalHook("pre-exit").Once().AndCallFunc(preExitFunc) 272 tester.ExpectLocalHook("pre-exit").Once().AndCallFunc(preExitFunc) 273 }