github.com/alloyci/alloy-runner@v1.0.1-0.20180222164613-925503ccafd6/executors/docker/executor_docker_command_test.go (about) 1 package docker_test 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "net/url" 8 "os" 9 "os/exec" 10 "regexp" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/hashicorp/go-version" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 19 "gitlab.com/gitlab-org/gitlab-runner/common" 20 "gitlab.com/gitlab-org/gitlab-runner/executors/docker" 21 "gitlab.com/gitlab-org/gitlab-runner/helpers" 22 "gitlab.com/gitlab-org/gitlab-runner/helpers/docker" 23 ) 24 25 func TestDockerCommandSuccessRun(t *testing.T) { 26 if helpers.SkipIntegrationTests(t, "docker", "info") { 27 return 28 } 29 30 successfulBuild, err := common.GetRemoteSuccessfulBuild() 31 assert.NoError(t, err) 32 build := &common.Build{ 33 JobResponse: successfulBuild, 34 Runner: &common.RunnerConfig{ 35 RunnerSettings: common.RunnerSettings{ 36 Executor: "docker", 37 Docker: &common.DockerConfig{ 38 Image: "alpine", 39 }, 40 }, 41 }, 42 } 43 44 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 45 assert.NoError(t, err) 46 } 47 48 func TestDockerCommandNoRootImage(t *testing.T) { 49 if helpers.SkipIntegrationTests(t, "docker", "info") { 50 return 51 } 52 53 successfulBuild, err := common.GetRemoteSuccessfulBuildWithDumpedVariables() 54 55 assert.NoError(t, err) 56 successfulBuild.Image.Name = "registry.gitlab.com/gitlab-org/gitlab-runner/alpine-no-root" 57 build := &common.Build{ 58 JobResponse: successfulBuild, 59 Runner: &common.RunnerConfig{ 60 RunnerSettings: common.RunnerSettings{ 61 Executor: "docker", 62 Docker: &common.DockerConfig{}, 63 }, 64 }, 65 } 66 67 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 68 assert.NoError(t, err) 69 } 70 71 func TestDockerCommandBuildFail(t *testing.T) { 72 if helpers.SkipIntegrationTests(t, "docker", "info") { 73 return 74 } 75 76 failedBuild, err := common.GetRemoteFailedBuild() 77 assert.NoError(t, err) 78 build := &common.Build{ 79 JobResponse: failedBuild, 80 Runner: &common.RunnerConfig{ 81 RunnerSettings: common.RunnerSettings{ 82 Executor: "docker", 83 Docker: &common.DockerConfig{ 84 Image: "alpine", 85 }, 86 }, 87 }, 88 } 89 90 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 91 require.Error(t, err, "error") 92 assert.IsType(t, err, &common.BuildError{}) 93 assert.Contains(t, err.Error(), "exit code 1") 94 } 95 96 func TestDockerCommandWithAllowedImagesRun(t *testing.T) { 97 if helpers.SkipIntegrationTests(t, "docker", "info") { 98 return 99 } 100 101 successfulBuild, err := common.GetRemoteSuccessfulBuild() 102 successfulBuild.Image = common.Image{Name: "$IMAGE_NAME"} 103 successfulBuild.Variables = append(successfulBuild.Variables, common.JobVariable{ 104 Key: "IMAGE_NAME", 105 Value: "alpine", 106 Public: true, 107 Internal: false, 108 File: false, 109 }) 110 successfulBuild.Services = append(successfulBuild.Services, common.Image{Name: "docker:dind"}) 111 assert.NoError(t, err) 112 build := &common.Build{ 113 JobResponse: successfulBuild, 114 Runner: &common.RunnerConfig{ 115 RunnerSettings: common.RunnerSettings{ 116 Executor: "docker", 117 Docker: &common.DockerConfig{ 118 AllowedImages: []string{"alpine"}, 119 AllowedServices: []string{"docker:dind"}, 120 Privileged: true, 121 }, 122 }, 123 }, 124 } 125 126 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 127 assert.NoError(t, err) 128 } 129 130 func isDockerOlderThan17_07(t *testing.T) bool { 131 client, err := docker_helpers.New( 132 docker_helpers.DockerCredentials{}, docker.DockerAPIVersion) 133 require.NoError(t, err, "should be able to connect to docker") 134 135 types, err := client.Info(context.Background()) 136 require.NoError(t, err, "should be able to get docker info") 137 138 localVersion, err := version.NewVersion(types.ServerVersion) 139 require.NoError(t, err) 140 141 checkedVersion, err := version.NewVersion("17.07.0-ce") 142 require.NoError(t, err) 143 144 return localVersion.LessThan(checkedVersion) 145 } 146 147 func TestDockerCommandMissingImage(t *testing.T) { 148 if helpers.SkipIntegrationTests(t, "docker", "info") { 149 return 150 } 151 152 build := &common.Build{ 153 Runner: &common.RunnerConfig{ 154 RunnerSettings: common.RunnerSettings{ 155 Executor: "docker", 156 Docker: &common.DockerConfig{ 157 Image: "some/non-existing/image", 158 }, 159 }, 160 }, 161 } 162 163 err := build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 164 require.Error(t, err) 165 assert.IsType(t, &common.BuildError{}, err) 166 167 contains := "repository does not exist" 168 if isDockerOlderThan17_07(t) { 169 contains = "not found" 170 } 171 172 assert.Contains(t, err.Error(), contains) 173 } 174 175 func TestDockerCommandMissingTag(t *testing.T) { 176 if helpers.SkipIntegrationTests(t, "docker", "info") { 177 return 178 } 179 180 build := &common.Build{ 181 Runner: &common.RunnerConfig{ 182 RunnerSettings: common.RunnerSettings{ 183 Executor: "docker", 184 Docker: &common.DockerConfig{ 185 Image: "docker:missing-tag", 186 }, 187 }, 188 }, 189 } 190 191 err := build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 192 require.Error(t, err) 193 assert.IsType(t, &common.BuildError{}, err) 194 assert.Contains(t, err.Error(), "not found") 195 } 196 197 func TestDockerCommandBuildAbort(t *testing.T) { 198 if helpers.SkipIntegrationTests(t, "docker", "info") { 199 return 200 } 201 202 longRunningBuild, err := common.GetRemoteLongRunningBuild() 203 assert.NoError(t, err) 204 build := &common.Build{ 205 JobResponse: longRunningBuild, 206 Runner: &common.RunnerConfig{ 207 RunnerSettings: common.RunnerSettings{ 208 Executor: "docker", 209 Docker: &common.DockerConfig{ 210 Image: "alpine", 211 }, 212 }, 213 }, 214 SystemInterrupt: make(chan os.Signal, 1), 215 } 216 217 abortTimer := time.AfterFunc(time.Second, func() { 218 t.Log("Interrupt") 219 build.SystemInterrupt <- os.Interrupt 220 }) 221 defer abortTimer.Stop() 222 223 timeoutTimer := time.AfterFunc(time.Minute, func() { 224 t.Log("Timedout") 225 t.FailNow() 226 }) 227 defer timeoutTimer.Stop() 228 229 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 230 assert.EqualError(t, err, "aborted: interrupt") 231 } 232 233 func TestDockerCommandBuildCancel(t *testing.T) { 234 if helpers.SkipIntegrationTests(t, "docker", "info") { 235 return 236 } 237 238 longRunningBuild, err := common.GetRemoteLongRunningBuild() 239 assert.NoError(t, err) 240 build := &common.Build{ 241 JobResponse: longRunningBuild, 242 Runner: &common.RunnerConfig{ 243 RunnerSettings: common.RunnerSettings{ 244 Executor: "docker", 245 Docker: &common.DockerConfig{ 246 Image: "alpine", 247 }, 248 }, 249 }, 250 } 251 252 trace := &common.Trace{Writer: os.Stdout} 253 254 abortTimer := time.AfterFunc(time.Second, func() { 255 t.Log("Interrupt") 256 trace.CancelFunc() 257 }) 258 defer abortTimer.Stop() 259 260 timeoutTimer := time.AfterFunc(time.Minute, func() { 261 t.Log("Timedout") 262 t.FailNow() 263 }) 264 defer timeoutTimer.Stop() 265 266 err = build.Run(&common.Config{}, trace) 267 assert.IsType(t, err, &common.BuildError{}) 268 assert.EqualError(t, err, "canceled") 269 } 270 271 func TestDockerCommandTwoServicesFromOneImage(t *testing.T) { 272 if helpers.SkipIntegrationTests(t, "docker", "info") { 273 return 274 } 275 276 successfulBuild, err := common.GetRemoteSuccessfulBuild() 277 successfulBuild.Services = common.Services{ 278 {Name: "alpine", Alias: "service-1"}, 279 {Name: "alpine", Alias: "service-2"}, 280 } 281 assert.NoError(t, err) 282 build := &common.Build{ 283 JobResponse: successfulBuild, 284 Runner: &common.RunnerConfig{ 285 RunnerSettings: common.RunnerSettings{ 286 Executor: "docker", 287 Docker: &common.DockerConfig{ 288 Image: "alpine", 289 }, 290 }, 291 }, 292 } 293 294 var buffer bytes.Buffer 295 296 err = build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 297 assert.NoError(t, err) 298 str := buffer.String() 299 300 re, err := regexp.Compile("(?m)Conflict. The container name [^ ]+ is already in use by container") 301 require.NoError(t, err) 302 assert.NotRegexp(t, re, str, "Both service containers should be started and use different name") 303 } 304 305 func TestDockerCommandOutput(t *testing.T) { 306 if helpers.SkipIntegrationTests(t, "docker", "info") { 307 return 308 } 309 310 successfulBuild, err := common.GetRemoteSuccessfulBuild() 311 assert.NoError(t, err) 312 build := &common.Build{ 313 JobResponse: successfulBuild, 314 Runner: &common.RunnerConfig{ 315 RunnerSettings: common.RunnerSettings{ 316 Executor: "docker", 317 Docker: &common.DockerConfig{ 318 Image: "alpine", 319 }, 320 }, 321 }, 322 } 323 324 var buffer bytes.Buffer 325 326 err = build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 327 assert.NoError(t, err) 328 329 re, err := regexp.Compile("(?m)^Cloning into '/builds/gitlab-org/gitlab-test'...") 330 assert.NoError(t, err) 331 assert.Regexp(t, re, buffer.String()) 332 } 333 334 func TestDockerPrivilegedServiceAccessingBuildsFolder(t *testing.T) { 335 if helpers.SkipIntegrationTests(t, "docker", "info") { 336 return 337 } 338 339 commands := []string{ 340 "docker info", 341 "docker run -v $(pwd):$(pwd) -w $(pwd) alpine touch test", 342 "cat test", 343 } 344 345 strategies := []string{ 346 "fetch", 347 "clone", 348 } 349 350 for _, strategy := range strategies { 351 t.Log("Testing", strategy, "strategy...") 352 longRunningBuild, err := common.GetRemoteLongRunningBuild() 353 assert.NoError(t, err) 354 build := &common.Build{ 355 JobResponse: longRunningBuild, 356 Runner: &common.RunnerConfig{ 357 RunnerSettings: common.RunnerSettings{ 358 Executor: "docker", 359 Docker: &common.DockerConfig{ 360 Image: "alpine", 361 Privileged: true, 362 }, 363 }, 364 }, 365 } 366 build.Steps = common.Steps{ 367 common.Step{ 368 Name: common.StepNameScript, 369 Script: common.StepScript(commands), 370 When: common.StepWhenOnSuccess, 371 AllowFailure: false, 372 }, 373 } 374 build.Image.Name = "docker:git" 375 build.Services = common.Services{ 376 common.Image{ 377 Name: "docker:dind", 378 }, 379 } 380 build.Variables = append(build.Variables, common.JobVariable{ 381 Key: "GIT_STRATEGY", Value: strategy, 382 }) 383 384 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 385 assert.NoError(t, err) 386 } 387 } 388 389 func getTestDockerJob(t *testing.T) *common.Build { 390 commands := []string{ 391 "docker info", 392 } 393 394 longRunningBuild, err := common.GetRemoteLongRunningBuild() 395 assert.NoError(t, err) 396 397 build := &common.Build{ 398 JobResponse: longRunningBuild, 399 Runner: &common.RunnerConfig{ 400 RunnerSettings: common.RunnerSettings{ 401 Executor: "docker", 402 Docker: &common.DockerConfig{ 403 Image: "alpine", 404 Privileged: true, 405 }, 406 }, 407 }, 408 } 409 build.Steps = common.Steps{ 410 common.Step{ 411 Name: common.StepNameScript, 412 Script: common.StepScript(commands), 413 When: common.StepWhenOnSuccess, 414 AllowFailure: false, 415 }, 416 } 417 418 return build 419 } 420 421 func TestDockerExtendedConfigurationFromJob(t *testing.T) { 422 if helpers.SkipIntegrationTests(t, "docker", "info") { 423 return 424 } 425 426 examples := []struct { 427 image common.Image 428 services common.Services 429 variables common.JobVariables 430 }{ 431 { 432 image: common.Image{ 433 Name: "$IMAGE_NAME", 434 Entrypoint: []string{"sh", "-c"}, 435 }, 436 services: common.Services{ 437 common.Image{ 438 Name: "$SERVICE_NAME", 439 Entrypoint: []string{"sh", "-c"}, 440 Command: []string{"dockerd-entrypoint.sh"}, 441 Alias: "my-docker-service", 442 }, 443 }, 444 variables: common.JobVariables{ 445 {Key: "DOCKER_HOST", Value: "tcp://my-docker-service:2375"}, 446 {Key: "IMAGE_NAME", Value: "docker:git"}, 447 {Key: "SERVICE_NAME", Value: "docker:dind"}, 448 }, 449 }, 450 { 451 image: common.Image{ 452 Name: "$IMAGE_NAME", 453 }, 454 services: common.Services{ 455 common.Image{ 456 Name: "$SERVICE_NAME", 457 }, 458 }, 459 variables: common.JobVariables{ 460 {Key: "DOCKER_HOST", Value: "tcp://docker:2375"}, 461 {Key: "IMAGE_NAME", Value: "docker:git"}, 462 {Key: "SERVICE_NAME", Value: "docker:dind"}, 463 }, 464 }, 465 } 466 467 for exampleID, example := range examples { 468 t.Run(fmt.Sprintf("example-%d", exampleID), func(t *testing.T) { 469 build := getTestDockerJob(t) 470 build.Image = example.image 471 build.Services = example.services 472 build.Variables = append(build.Variables, example.variables...) 473 474 err := build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 475 assert.NoError(t, err) 476 }) 477 } 478 } 479 480 func runTestJobWithOutput(t *testing.T, build *common.Build) (output string) { 481 var buffer bytes.Buffer 482 483 err := build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 484 assert.NoError(t, err) 485 486 output = buffer.String() 487 return 488 } 489 490 func TestCacheInContainer(t *testing.T) { 491 if helpers.SkipIntegrationTests(t, "docker", "info") { 492 return 493 } 494 495 successfulBuild, err := common.GetRemoteSuccessfulBuild() 496 assert.NoError(t, err) 497 498 successfulBuild.JobInfo.ProjectID = int(time.Now().Unix()) 499 successfulBuild.Steps[0].Script = common.StepScript{ 500 "(test -d cached/ && ls -lh cached/) || echo \"no cached directory\"", 501 "(test -f cached/date && cat cached/date) || echo \"no cached date\"", 502 "mkdir -p cached", 503 "date > cached/date", 504 } 505 successfulBuild.Cache = common.Caches{ 506 common.Cache{ 507 Key: "key", 508 Paths: common.ArtifactPaths{"cached/*"}, 509 Policy: common.CachePolicyPullPush, 510 }, 511 } 512 513 build := &common.Build{ 514 JobResponse: successfulBuild, 515 Runner: &common.RunnerConfig{ 516 RunnerSettings: common.RunnerSettings{ 517 Executor: "docker", 518 Docker: &common.DockerConfig{ 519 Image: "alpine", 520 Volumes: []string{"/cache"}, 521 }, 522 }, 523 }, 524 } 525 526 cacheNotPresentRE := regexp.MustCompile("(?m)^no cached directory") 527 skipCacheDownload := "Not downloading cache key due to policy" 528 skipCacheUpload := "Not uploading cache key due to policy" 529 530 // The first job lacks any cache to pull, but tries to both pull and push 531 output := runTestJobWithOutput(t, build) 532 assert.Regexp(t, cacheNotPresentRE, output, "First job execution should not have cached data") 533 assert.NotContains(t, output, skipCacheDownload, "Cache download should be performed with policy: %s", common.CachePolicyPullPush) 534 assert.NotContains(t, output, skipCacheUpload, "Cache upload should be performed with policy: %s", common.CachePolicyPullPush) 535 536 // pull-only jobs should skip the push step 537 build.JobResponse.Cache[0].Policy = common.CachePolicyPull 538 output = runTestJobWithOutput(t, build) 539 assert.NotRegexp(t, cacheNotPresentRE, output, "Second job execution should have cached data") 540 assert.NotContains(t, output, skipCacheDownload, "Cache download should be performed with policy: %s", common.CachePolicyPull) 541 assert.Contains(t, output, skipCacheUpload, "Cache upload should be skipped with policy: %s", common.CachePolicyPull) 542 543 // push-only jobs should skip the pull step 544 build.JobResponse.Cache[0].Policy = common.CachePolicyPush 545 output = runTestJobWithOutput(t, build) 546 assert.Regexp(t, cacheNotPresentRE, output, "Third job execution should not have cached data") 547 assert.Contains(t, output, skipCacheDownload, "Cache download be skipped with policy: push") 548 assert.NotContains(t, output, skipCacheUpload, "Cache upload should be performed with policy: push") 549 } 550 551 func TestDockerImageNameFromVariable(t *testing.T) { 552 if helpers.SkipIntegrationTests(t, "docker", "info") { 553 return 554 } 555 556 successfulBuild, err := common.GetRemoteSuccessfulBuild() 557 successfulBuild.Variables = append(successfulBuild.Variables, common.JobVariable{ 558 Key: "CI_REGISTRY_IMAGE", 559 Value: "alpine", 560 }) 561 successfulBuild.Image = common.Image{ 562 Name: "$CI_REGISTRY_IMAGE", 563 } 564 assert.NoError(t, err) 565 build := &common.Build{ 566 JobResponse: successfulBuild, 567 Runner: &common.RunnerConfig{ 568 RunnerSettings: common.RunnerSettings{ 569 Executor: "docker", 570 Docker: &common.DockerConfig{ 571 Image: "alpine", 572 AllowedServices: []string{"alpine"}, 573 }, 574 }, 575 }, 576 } 577 578 re := regexp.MustCompile("(?m)^ERROR: The [^ ]+ is not present on list of allowed images") 579 580 output := runTestJobWithOutput(t, build) 581 assert.NotRegexp(t, re, output, "Image's name should be expanded from variable") 582 } 583 584 func TestDockerServiceNameFromVariable(t *testing.T) { 585 if helpers.SkipIntegrationTests(t, "docker", "info") { 586 return 587 } 588 589 successfulBuild, err := common.GetRemoteSuccessfulBuild() 590 successfulBuild.Variables = append(successfulBuild.Variables, common.JobVariable{ 591 Key: "CI_REGISTRY_IMAGE", 592 Value: "alpine", 593 }) 594 successfulBuild.Services = append(successfulBuild.Services, common.Image{ 595 Name: "$CI_REGISTRY_IMAGE", 596 }) 597 assert.NoError(t, err) 598 build := &common.Build{ 599 JobResponse: successfulBuild, 600 Runner: &common.RunnerConfig{ 601 RunnerSettings: common.RunnerSettings{ 602 Executor: "docker", 603 Docker: &common.DockerConfig{ 604 Image: "alpine", 605 AllowedServices: []string{"alpine"}, 606 }, 607 }, 608 }, 609 } 610 611 re := regexp.MustCompile("(?m)^ERROR: The [^ ]+ is not present on list of allowed services") 612 613 output := runTestJobWithOutput(t, build) 614 assert.NotRegexp(t, re, output, "Service's name should be expanded from variable") 615 } 616 617 func runDockerInDocker(version string) (id string, err error) { 618 cmd := exec.Command("docker", "run", "--detach", "--privileged", "-p", "2375", "docker:"+version+"-dind") 619 cmd.Stderr = os.Stderr 620 data, err := cmd.Output() 621 if err != nil { 622 return 623 } 624 id = strings.TrimSpace(string(data)) 625 return 626 } 627 628 func getDockerCredentials(id string) (credentials docker_helpers.DockerCredentials, err error) { 629 cmd := exec.Command("docker", "port", id, "2375") 630 cmd.Stderr = os.Stderr 631 data, err := cmd.Output() 632 if err != nil { 633 return 634 } 635 636 hostPort := strings.Split(strings.TrimSpace(string(data)), ":") 637 if dockerHost, err := url.Parse(os.Getenv("DOCKER_HOST")); err == nil { 638 dockerHostPort := strings.Split(dockerHost.Host, ":") 639 hostPort[0] = dockerHostPort[0] 640 } else if hostPort[0] == "0.0.0.0" { 641 hostPort[0] = "localhost" 642 } 643 credentials.Host = "tcp://" + hostPort[0] + ":" + hostPort[1] 644 return 645 } 646 647 func waitForDocker(credentials docker_helpers.DockerCredentials) error { 648 client, err := docker_helpers.New(credentials, docker.DockerAPIVersion) 649 if err != nil { 650 return err 651 } 652 653 for i := 0; i < 20; i++ { 654 _, err = client.Info(context.Background()) 655 if err == nil { 656 break 657 } 658 time.Sleep(time.Second) 659 } 660 return err 661 } 662 663 func testDockerVersion(t *testing.T, version string) { 664 t.Log("Running docker", version, "...") 665 id, err := runDockerInDocker(version) 666 if err != nil { 667 t.Error("Docker run:", err) 668 return 669 } 670 671 defer func() { 672 exec.Command("docker", "rm", "-f", "-v", id).Run() 673 }() 674 675 t.Log("Getting address of", version, "...") 676 credentials, err := getDockerCredentials(id) 677 if err != nil { 678 t.Error("Docker credentials:", err) 679 return 680 } 681 682 t.Log("Connecting to", credentials.Host, "...") 683 err = waitForDocker(credentials) 684 if err != nil { 685 t.Error("Wait for docker:", err) 686 return 687 } 688 689 t.Log("Docker", version, "is running at", credentials.Host) 690 691 successfulBuild, err := common.GetRemoteSuccessfulBuild() 692 assert.NoError(t, err) 693 build := &common.Build{ 694 JobResponse: successfulBuild, 695 Runner: &common.RunnerConfig{ 696 RunnerSettings: common.RunnerSettings{ 697 Executor: "docker", 698 Docker: &common.DockerConfig{ 699 Image: "alpine", 700 DockerCredentials: credentials, 701 CPUS: "0.1", 702 }, 703 }, 704 }, 705 } 706 707 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 708 assert.NoError(t, err) 709 } 710 711 func TestDocker1_8Compatibility(t *testing.T) { 712 if helpers.SkipIntegrationTests(t, "docker", "info") { 713 return 714 } 715 if os.Getenv("CI") != "" { 716 t.Skip("This test doesn't work in nested dind") 717 return 718 } 719 720 testDockerVersion(t, "1.8") 721 } 722 723 func TestDocker1_9Compatibility(t *testing.T) { 724 if helpers.SkipIntegrationTests(t, "docker", "info") { 725 return 726 } 727 if os.Getenv("CI") != "" { 728 t.Skip("This test doesn't work in nested dind") 729 return 730 } 731 732 testDockerVersion(t, "1.9") 733 } 734 735 func TestDocker1_10Compatibility(t *testing.T) { 736 if helpers.SkipIntegrationTests(t, "docker", "info") { 737 return 738 } 739 if os.Getenv("CI") != "" { 740 t.Skip("This test doesn't work in nested dind") 741 return 742 } 743 744 testDockerVersion(t, "1.10") 745 } 746 747 func TestDocker1_11Compatibility(t *testing.T) { 748 if helpers.SkipIntegrationTests(t, "docker", "info") { 749 return 750 } 751 if os.Getenv("CI") != "" { 752 t.Skip("This test doesn't work in nested dind") 753 return 754 } 755 756 testDockerVersion(t, "1.11") 757 } 758 759 func TestDocker1_12Compatibility(t *testing.T) { 760 if helpers.SkipIntegrationTests(t, "docker", "info") { 761 return 762 } 763 if os.Getenv("CI") != "" { 764 t.Skip("This test doesn't work in nested dind") 765 return 766 } 767 768 testDockerVersion(t, "1.12") 769 } 770 771 func TestDocker1_13Compatibility(t *testing.T) { 772 if helpers.SkipIntegrationTests(t, "docker", "info") { 773 return 774 } 775 if os.Getenv("CI") != "" { 776 t.Skip("This test doesn't work in nested dind") 777 return 778 } 779 780 testDockerVersion(t, "1.13") 781 } 782 783 func TestDockerCommandWithBrokenGitSSLCAInfo(t *testing.T) { 784 if helpers.SkipIntegrationTests(t, "docker", "info") { 785 return 786 } 787 788 successfulBuild, err := common.GetRemoteBrokenTLSBuild() 789 assert.NoError(t, err) 790 build := &common.Build{ 791 JobResponse: successfulBuild, 792 Runner: &common.RunnerConfig{ 793 RunnerCredentials: common.RunnerCredentials{ 794 URL: "https://gitlab.com", 795 }, 796 RunnerSettings: common.RunnerSettings{ 797 Executor: "docker", 798 Docker: &common.DockerConfig{ 799 Image: "alpine", 800 }, 801 }, 802 }, 803 } 804 805 var buffer bytes.Buffer 806 807 err = build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 808 assert.Error(t, err) 809 out := buffer.String() 810 assert.Contains(t, out, "Cloning repository") 811 assert.NotContains(t, out, "Updating/initializing submodules") 812 } 813 814 func TestDockerCommandWithGitSSLCAInfo(t *testing.T) { 815 if helpers.SkipIntegrationTests(t, "docker", "info") { 816 return 817 } 818 819 successfulBuild, err := common.GetRemoteGitLabComTLSBuild() 820 assert.NoError(t, err) 821 build := &common.Build{ 822 JobResponse: successfulBuild, 823 Runner: &common.RunnerConfig{ 824 RunnerCredentials: common.RunnerCredentials{ 825 URL: "https://gitlab.com", 826 }, 827 RunnerSettings: common.RunnerSettings{ 828 Executor: "docker", 829 Docker: &common.DockerConfig{ 830 Image: "alpine", 831 }, 832 }, 833 }, 834 } 835 836 var buffer bytes.Buffer 837 838 err = build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 839 assert.NoError(t, err) 840 out := buffer.String() 841 assert.Contains(t, out, "Cloning repository") 842 assert.Contains(t, out, "Updating/initializing submodules") 843 } 844 845 func TestDockerCommandWithHelperImageConfig(t *testing.T) { 846 if helpers.SkipIntegrationTests(t, "docker", "info") { 847 return 848 } 849 850 helperImageConfig := "gitlab/gitlab-runner-helper:x86_64-64eea86c" 851 852 successfulBuild, err := common.GetRemoteSuccessfulBuild() 853 assert.NoError(t, err) 854 build := &common.Build{ 855 JobResponse: successfulBuild, 856 Runner: &common.RunnerConfig{ 857 RunnerSettings: common.RunnerSettings{ 858 Executor: "docker", 859 Docker: &common.DockerConfig{ 860 Image: "alpine", 861 HelperImage: helperImageConfig, 862 }, 863 }, 864 }, 865 } 866 867 var buffer bytes.Buffer 868 err = build.Run(&common.Config{}, &common.Trace{Writer: &buffer}) 869 assert.NoError(t, err) 870 out := buffer.String() 871 assert.Contains(t, out, "Pulling docker image "+helperImageConfig) 872 assert.Contains(t, out, "Using docker image sha256:bbd86c6ba107ae2feb8dbf9024df4b48597c44e1b584a3d901bba91f7fc500e3 for gitlab/gitlab-runner-helper:x86_64-64eea86c ...") 873 } 874 875 func TestDockerCommandWithDoingPruneAndAfterScript(t *testing.T) { 876 if helpers.SkipIntegrationTests(t, "docker", "info") { 877 return 878 } 879 880 successfulBuild, err := common.GetRemoteSuccessfulBuildWithAfterScript() 881 882 // This scripts removes self-created containers that do exit 883 // It will fail if: cannot be removed, or no containers is found 884 // It is assuming that name of each runner created container starts 885 // with `runner-doprune-` 886 successfulBuild.Steps[0].Script = common.StepScript{ 887 "docker ps -a -f status=exited | grep runner-doprune-", 888 "docker rm $(docker ps -a -f status=exited | grep runner-doprune- | awk '{print $1}')", 889 } 890 891 assert.NoError(t, err) 892 build := &common.Build{ 893 JobResponse: successfulBuild, 894 Runner: &common.RunnerConfig{ 895 RunnerCredentials: common.RunnerCredentials{ 896 Token: "doprune", 897 }, 898 RunnerSettings: common.RunnerSettings{ 899 Executor: "docker", 900 Docker: &common.DockerConfig{ 901 Image: "docker:git", 902 Volumes: []string{ 903 "/var/run/docker.sock:/var/run/docker.sock", 904 }, 905 }, 906 }, 907 }, 908 } 909 910 err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout}) 911 assert.NoError(t, err) 912 }