This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
dagger/pkg/buildkitd/buildkitd.go
Andrea Luzzardi 14ff14ea4f automatically start/upgrade buildkitd
- Automatically start a buildkit daemon if no BUILDKIT_HOST is
  provided (and if not already started)
- Customization of BUILDKIT_HOST is still possible, just like before
- Automatically upgrade the managed daemon to the version used by dagger
  if necessary
- Add CI test to make sure the managed buildkit and the vendored
  buildkit versions match

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
2021-03-02 18:37:30 -08:00

169 lines
3.2 KiB
Go

package buildkitd
import (
"context"
"fmt"
"os/exec"
"strings"
"github.com/docker/distribution/reference"
"github.com/rs/zerolog/log"
)
const (
image = "moby/buildkit"
version = "v0.8.2"
imageVersion = image + ":" + version
containerName = "dagger-buildkitd"
)
func Start(ctx context.Context) (string, error) {
lg := log.Ctx(ctx)
// Attempt to detect the current buildkit version
currentVersion, err := getBuildkitVersion(ctx)
if err != nil {
// If that failed, it might either be because buildkitd is not running
// or because the docker CLI is out of service.
if err := checkDocker(ctx); err != nil {
return "", err
}
currentVersion = ""
lg.Debug().Msg("no buildkit daemon detected")
} else {
lg.Debug().Str("version", currentVersion).Msg("detected buildkit version")
}
if currentVersion != version {
if currentVersion != "" {
lg.
Info().
Str("version", version).
Msg("upgrading buildkit")
if err := remvoveBuildkit(ctx); err != nil {
return "", err
}
} else {
lg.
Info().
Str("version", version).
Msg("starting buildkit")
}
if err := startBuildkit(ctx); err != nil {
return "", err
}
}
return fmt.Sprintf("docker-container://%s", containerName), nil
}
// ensure the docker CLI is available and properly set up (e.g. permissions to
// communicate with the daemon, etc)
func checkDocker(ctx context.Context) error {
cmd := exec.CommandContext(ctx, "docker", "info")
output, err := cmd.CombinedOutput()
if err != nil {
log.
Ctx(ctx).
Error().
Err(err).
Bytes("output", output).
Msg("failed to run docker")
return err
}
return nil
}
func startBuildkit(ctx context.Context) error {
lg := log.
Ctx(ctx).
With().
Str("version", version).
Logger()
lg.Debug().Msg("pulling buildkit image")
cmd := exec.CommandContext(ctx,
"docker",
"pull",
imageVersion,
)
output, err := cmd.CombinedOutput()
if err != nil {
lg.
Error().
Err(err).
Bytes("output", output).
Msg("failed to pull buildkit image")
return err
}
cmd = exec.CommandContext(ctx,
"docker",
"run",
"-d",
"--restart", "always",
"--name", containerName,
"--privileged",
imageVersion,
)
output, err = cmd.CombinedOutput()
if err != nil {
log.
Ctx(ctx).
Error().
Err(err).
Bytes("output", output).
Msg("unable to start buildkitd")
return err
}
return nil
}
func remvoveBuildkit(ctx context.Context) error {
lg := log.
Ctx(ctx)
cmd := exec.CommandContext(ctx,
"docker",
"rm",
"-fv",
containerName,
)
output, err := cmd.CombinedOutput()
if err != nil {
lg.
Error().
Err(err).
Bytes("output", output).
Msg("failed to stop buildkit")
return err
}
return nil
}
func getBuildkitVersion(ctx context.Context) (string, error) {
cmd := exec.CommandContext(ctx,
"docker",
"inspect",
"--format",
"{{.Config.Image}}",
containerName,
)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
ref, err := reference.ParseNormalizedNamed(strings.TrimSpace(string(output)))
if err != nil {
return "", err
}
tag, ok := ref.(reference.Tagged)
if !ok {
return "", fmt.Errorf("failed to parse image: %s", output)
}
return tag.Tag(), nil
}