github.com/bshelton229/agent@v3.5.4+incompatible/bootstrap/docker.go (about)

     1  package bootstrap
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/buildkite/agent/bootstrap/shell"
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  var dockerEnv = []string{
    12  	`BUILDKITE_DOCKER_COMPOSE_CONTAINER`,
    13  	`BUILDKITE_DOCKER_COMPOSE_FILE`,
    14  	`BUILDKITE_DOCKER`,
    15  	`BUILDKITE_DOCKER_FILE`,
    16  	`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`,
    17  	`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`,
    18  }
    19  
    20  func hasDeprecatedDockerIntegration(sh *shell.Shell) bool {
    21  	for _, k := range dockerEnv {
    22  		if sh.Env.Exists(k) {
    23  			return true
    24  		}
    25  	}
    26  	return false
    27  }
    28  
    29  func runDeprecatedDockerIntegration(sh *shell.Shell, cmd []string) error {
    30  	var warnNotSet = func(k1, k2 string) {
    31  		sh.Warningf("%s is set, but without %s, which it requires. You should be able to safely remove this from your pipeline.", k1, k2)
    32  	}
    33  
    34  	switch {
    35  	case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_CONTAINER`):
    36  		sh.Warningf("BUILDKITE_DOCKER_COMPOSE_CONTAINER is set, which is deprecated in Agent v3 and will be removed in v4. Consider using the :docker: docker-compose plugin instead at https://github.com/buildkite-plugins/docker-compose-buildkite-plugin.")
    37  		return runDockerComposeCommand(sh, cmd)
    38  
    39  	case sh.Env.Exists(`BUILDKITE_DOCKER`):
    40  		sh.Warningf("BUILDKITE_DOCKER is set, which is deprecated in Agent v3 and will be removed in v4. Consider using the docker plugin instead at https://github.com/buildkite-plugins/docker-buildkite-plugin.")
    41  		return runDockerCommand(sh, cmd)
    42  
    43  	case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_FILE`):
    44  		warnNotSet(`BUILDKITE_DOCKER_COMPOSE_FILE`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`)
    45  
    46  	case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`):
    47  		warnNotSet(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`)
    48  
    49  	case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`):
    50  		warnNotSet(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`)
    51  
    52  	case sh.Env.Exists(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`):
    53  		warnNotSet(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, `BUILDKITE_DOCKER_COMPOSE_CONTAINER`)
    54  	}
    55  
    56  	return errors.New("Failed to find any docker env")
    57  }
    58  
    59  func tearDownDeprecatedDockerIntegration(sh *shell.Shell) error {
    60  	if container, ok := sh.Env.Get(`DOCKER_CONTAINER`); ok {
    61  		sh.Printf("~~~ Cleaning up Docker containers")
    62  
    63  		if err := sh.Run("docker", "rm", "-f", "-v", container); err != nil {
    64  			return err
    65  		}
    66  	} else if projectName, ok := sh.Env.Get(`COMPOSE_PROJ_NAME`); ok {
    67  		sh.Printf("~~~ Cleaning up Docker containers")
    68  
    69  		// Friendly kill
    70  		_ = runDockerCompose(sh, projectName, "kill")
    71  
    72  		if sh.Env.GetBool(`BUILDKITE_DOCKER_COMPOSE_LEAVE_VOLUMES`, false) {
    73  			_ = runDockerCompose(sh, projectName, "rm", "--force", "--all")
    74  		} else {
    75  			_ = runDockerCompose(sh, projectName, "rm", "--force", "--all", "-v")
    76  		}
    77  
    78  		return runDockerCompose(sh, projectName, "down")
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  // runDockerCommand executes a command inside a docker container that is built as needed
    85  // Ported from https://github.com/buildkite/agent/blob/2b8f1d569b659e07de346c0e3ae7090cb98e49ba/templates/bootstrap.sh#L439
    86  func runDockerCommand(sh *shell.Shell, cmd []string) error {
    87  	jobId, _ := sh.Env.Get(`BUILDKITE_JOB_ID`)
    88  	dockerContainer := fmt.Sprintf("buildkite_%s_container", jobId)
    89  	dockerImage := fmt.Sprintf("buildkite_%s_image", jobId)
    90  
    91  	dockerFile, _ := sh.Env.Get(`BUILDKITE_DOCKER_FILE`)
    92  	if dockerFile == "" {
    93  		dockerFile = "Dockerfile"
    94  	}
    95  
    96  	sh.Env.Set(`DOCKER_CONTAINER`, dockerContainer)
    97  	sh.Env.Set(`DOCKER_IMAGE`, dockerImage)
    98  
    99  	sh.Printf("~~~ :docker: Building Docker image %s", dockerImage)
   100  	if err := sh.Run("docker", "build", "-f", dockerFile, "-t", dockerImage, "."); err != nil {
   101  		return err
   102  	}
   103  
   104  	sh.Headerf(":docker: Running command (in Docker container)")
   105  	if err := sh.Run("docker", append([]string{"run", "--name", dockerContainer, dockerImage}, cmd...)...); err != nil {
   106  		return err
   107  	}
   108  
   109  	return nil
   110  }
   111  
   112  // runDockerComposeCommand executes a command with docker-compose
   113  // Ported from https://github.com/buildkite/agent/blob/2b8f1d569b659e07de346c0e3ae7090cb98e49ba/templates/bootstrap.sh#L462
   114  func runDockerComposeCommand(sh *shell.Shell, cmd []string) error {
   115  	composeContainer, _ := sh.Env.Get(`BUILDKITE_DOCKER_COMPOSE_CONTAINER`)
   116  	jobId, _ := sh.Env.Get(`BUILDKITE_JOB_ID`)
   117  
   118  	// Compose strips dashes and underscores, so we'll remove them
   119  	// to match the docker container names
   120  	projectName := strings.Replace(fmt.Sprintf("buildkite%s", jobId), "-", "", -1)
   121  
   122  	sh.Env.Set(`COMPOSE_PROJ_NAME`, projectName)
   123  	sh.Headerf(":docker: Building Docker images")
   124  
   125  	if sh.Env.GetBool(`BUILDKITE_DOCKER_COMPOSE_BUILD_ALL`, false) {
   126  		if err := runDockerCompose(sh, projectName, "build", "--pull"); err != nil {
   127  			return err
   128  		}
   129  	} else {
   130  		if err := runDockerCompose(sh, projectName, "build", "--pull", composeContainer); err != nil {
   131  			return err
   132  		}
   133  	}
   134  
   135  	sh.Headerf(":docker: Running command (in Docker Compose container)")
   136  	return runDockerCompose(sh, projectName, append([]string{"run", composeContainer}, cmd...)...)
   137  }
   138  
   139  func runDockerCompose(sh *shell.Shell, projectName string, commandArgs ...string) error {
   140  	args := []string{}
   141  
   142  	composeFile, _ := sh.Env.Get(`BUILDKITE_DOCKER_COMPOSE_FILE`)
   143  	if composeFile == "" {
   144  		composeFile = "docker-compose.yml"
   145  	}
   146  
   147  	// composeFile might be multiple files, spaces or colons
   148  	for _, chunk := range strings.Fields(composeFile) {
   149  		for _, file := range strings.Split(chunk, ":") {
   150  			args = append(args, "-f", file)
   151  		}
   152  	}
   153  
   154  	args = append(args, "-p", projectName)
   155  
   156  	if sh.Env.GetBool(`BUILDKITE_AGENT_DEBUG`, false) {
   157  		args = append(args, "--verbose")
   158  	}
   159  
   160  	args = append(args, commandArgs...)
   161  	return sh.Run("docker-compose", args...)
   162  }