2024-08-01 22:43:18 +00:00
|
|
|
// Podman driver
|
|
|
|
//
|
|
|
|
// Abstracts interactions with Podman commands via the ContainerDriver interface.
|
2024-08-23 03:11:00 +00:00
|
|
|
package driver
|
2024-08-01 22:43:18 +00:00
|
|
|
|
|
|
|
import (
|
2024-08-12 03:23:41 +00:00
|
|
|
logger "courgette/internal/logging"
|
|
|
|
"fmt"
|
2024-08-01 22:43:18 +00:00
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
)
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
// 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...)
|
2024-08-01 22:43:18 +00:00
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
return cmd
|
|
|
|
}
|
2024-08-01 22:43:18 +00:00
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
type PodmanDriver struct{}
|
|
|
|
|
|
|
|
func (d PodmanDriver) Pull(uri string) error {
|
|
|
|
return podmanCommand("pull", uri).Run()
|
2024-08-01 22:43:18 +00:00
|
|
|
}
|
|
|
|
|
2024-08-12 03:23:41 +00:00
|
|
|
// Sets up a new container with an attached workspace volume.
|
|
|
|
//
|
|
|
|
// The volume created is labeled with `owner=<containerName>` so it
|
|
|
|
// can be easily collected and cleaned up on stop.
|
2024-09-02 14:14:59 +00:00
|
|
|
func (d PodmanDriver) Start(uri string, containerName string, cachePath string) error {
|
2024-08-12 03:23:41 +00:00
|
|
|
volumeName := fmt.Sprintf("%s-workspace", containerName)
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
if err := podmanCommand("volume", "create", volumeName, "--label", fmt.Sprintf("owner=%s", containerName)).Run(); err != nil {
|
2024-08-12 03:23:41 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-09-02 14:14:59 +00:00
|
|
|
if err := podmanCommand("run", "-td", "--name", containerName, "-v", fmt.Sprintf("%s:/workspace", volumeName), "-v", fmt.Sprintf("%s:/cache:ro", cachePath), uri).Run(); err != nil {
|
2024-08-01 22:43:18 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-08-12 03:23:41 +00:00
|
|
|
// Stops a container and removes any volumes labelled with its name
|
|
|
|
// as owner.
|
2024-08-01 22:43:18 +00:00
|
|
|
func (d PodmanDriver) Stop(containerName string) error {
|
2024-09-02 04:46:21 +00:00
|
|
|
if err := podmanCommand("rm", "-f", "-t", "2", containerName).Run(); err != nil {
|
2024-08-12 03:23:41 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
if err := podmanCommand("wait", containerName, "--ignore").Run(); err != nil {
|
2024-08-12 03:23:41 +00:00
|
|
|
logger.Error("%+v", err)
|
|
|
|
}
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
if err := podmanCommand("volume", "prune", "--filter", fmt.Sprintf("label=owner=%s", containerName), "-f").Run(); err != nil {
|
2024-08-01 22:43:18 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-08-21 17:46:57 +00:00
|
|
|
func (d PodmanDriver) Exec(containerId string, command string, options CommandOptions) CommandResult {
|
2024-08-21 03:35:49 +00:00
|
|
|
envArgs := []string{}
|
|
|
|
|
2024-08-21 17:46:57 +00:00
|
|
|
for key, value := range options.Env {
|
2024-08-21 03:35:49 +00:00
|
|
|
envArgs = append(envArgs, fmt.Sprintf("-e=%s=%s", key, value))
|
|
|
|
}
|
|
|
|
|
|
|
|
commandArgs := []string{
|
|
|
|
"exec",
|
|
|
|
"--workdir",
|
2024-08-21 17:46:57 +00:00
|
|
|
options.Cwd,
|
2024-08-21 03:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
commandArgs = append(commandArgs, envArgs...)
|
|
|
|
|
|
|
|
commandArgs = append(commandArgs, containerId,
|
2024-08-23 03:38:32 +00:00
|
|
|
options.Shell,
|
2024-08-21 03:35:49 +00:00
|
|
|
"-c",
|
|
|
|
command,
|
|
|
|
)
|
|
|
|
|
2024-09-02 04:46:21 +00:00
|
|
|
cmd := podmanCommand(commandArgs...)
|
2024-08-02 20:38:18 +00:00
|
|
|
err := cmd.Run()
|
|
|
|
|
|
|
|
return CommandResult{
|
|
|
|
Error: err,
|
|
|
|
ExitCode: cmd.ProcessState.ExitCode(),
|
|
|
|
}
|
2024-08-01 22:43:18 +00:00
|
|
|
}
|