// Podman driver // // Abstracts interactions with Podman commands via the ContainerDriver interface. package driver import ( logger "courgette/internal/logging" "fmt" "os" "os/exec" ) // Executes a Podman command and pipes output to stdout/stderr. // // The exec.Cmd pointer returned isn't ran. func podmanCommand(args ...string) *exec.Cmd { cmd := exec.Command("podman", args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd } type PodmanDriver struct{} func (d PodmanDriver) Pull(uri string) error { return podmanCommand("pull", uri).Run() } // Sets up a new container with an attached workspace volume. // // The volume created is labeled with `owner=` so it // can be easily collected and cleaned up on stop. func (d PodmanDriver) Start(uri string, containerName string, cachePath string) error { volumeName := fmt.Sprintf("%s-workspace", containerName) if err := podmanCommand("volume", "create", volumeName, "--label", fmt.Sprintf("owner=%s", containerName)).Run(); err != nil { return err } if err := podmanCommand("run", "-td", "--name", containerName, "-v", fmt.Sprintf("%s:/workspace", volumeName), "-v", fmt.Sprintf("%s:/cache:ro", cachePath), uri).Run(); err != nil { return err } return nil } // Stops a container and removes any volumes labelled with its name // as owner. func (d PodmanDriver) Stop(containerName string) error { if err := podmanCommand("rm", "-f", "-t", "2", containerName).Run(); err != nil { return err } if err := podmanCommand("wait", containerName, "--ignore").Run(); err != nil { logger.Error("%+v", err) } if err := podmanCommand("volume", "prune", "--filter", fmt.Sprintf("label=owner=%s", containerName), "-f").Run(); err != nil { return err } return nil } func (d PodmanDriver) Exec(containerId string, command string, options CommandOptions) CommandResult { envArgs := []string{} for key, value := range options.Env { envArgs = append(envArgs, fmt.Sprintf("-e=%s=%s", key, value)) } commandArgs := []string{ "exec", "--workdir", options.Cwd, } commandArgs = append(commandArgs, envArgs...) commandArgs = append(commandArgs, containerId, options.Shell, "-c", command, ) cmd := podmanCommand(commandArgs...) err := cmd.Run() return CommandResult{ Error: err, ExitCode: cmd.ProcessState.ExitCode(), } }