mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00

Removes gogo/protobuf from buildx and updates to a version of moby/buildkit where gogo is removed. This also changes how the proto files are generated. This is because newer versions of protobuf are more strict about name conflicts. If two files have the same name (even if they are relative paths) and are used in different protoc commands, they'll conflict in the registry. Since protobuf file generation doesn't work very well with `paths=source_relative`, this removes the `go:generate` expression and just relies on the dockerfile to perform the generation. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
147 lines
4.1 KiB
Go
147 lines
4.1 KiB
Go
package local
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"sync/atomic"
|
|
|
|
"github.com/docker/buildx/build"
|
|
cbuild "github.com/docker/buildx/controller/build"
|
|
"github.com/docker/buildx/controller/control"
|
|
controllererrors "github.com/docker/buildx/controller/errdefs"
|
|
controllerapi "github.com/docker/buildx/controller/pb"
|
|
"github.com/docker/buildx/controller/processes"
|
|
"github.com/docker/buildx/util/ioset"
|
|
"github.com/docker/buildx/util/progress"
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/moby/buildkit/client"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func NewLocalBuildxController(ctx context.Context, dockerCli command.Cli, logger progress.SubLogger) control.BuildxController {
|
|
return &localController{
|
|
dockerCli: dockerCli,
|
|
ref: "local",
|
|
processes: processes.NewManager(),
|
|
}
|
|
}
|
|
|
|
type buildConfig struct {
|
|
// TODO: these two structs should be merged
|
|
// Discussion: https://github.com/docker/buildx/pull/1640#discussion_r1113279719
|
|
resultCtx *build.ResultHandle
|
|
buildOptions *controllerapi.BuildOptions
|
|
}
|
|
|
|
type localController struct {
|
|
dockerCli command.Cli
|
|
ref string
|
|
buildConfig buildConfig
|
|
processes *processes.Manager
|
|
|
|
buildOnGoing atomic.Bool
|
|
}
|
|
|
|
func (b *localController) Build(ctx context.Context, options *controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (string, *client.SolveResponse, *build.Inputs, error) {
|
|
if !b.buildOnGoing.CompareAndSwap(false, true) {
|
|
return "", nil, nil, errors.New("build ongoing")
|
|
}
|
|
defer b.buildOnGoing.Store(false)
|
|
|
|
resp, res, dockerfileMappings, buildErr := cbuild.RunBuild(ctx, b.dockerCli, options, in, progress, true)
|
|
// NOTE: RunBuild can return *build.ResultHandle even on error.
|
|
if res != nil {
|
|
b.buildConfig = buildConfig{
|
|
resultCtx: res,
|
|
buildOptions: options,
|
|
}
|
|
if buildErr != nil {
|
|
buildErr = controllererrors.WrapBuild(buildErr, b.ref)
|
|
}
|
|
}
|
|
if buildErr != nil {
|
|
return "", nil, nil, buildErr
|
|
}
|
|
return b.ref, resp, dockerfileMappings, nil
|
|
}
|
|
|
|
func (b *localController) ListProcesses(ctx context.Context, ref string) (infos []*controllerapi.ProcessInfo, retErr error) {
|
|
if ref != b.ref {
|
|
return nil, errors.Errorf("unknown ref %q", ref)
|
|
}
|
|
return b.processes.ListProcesses(), nil
|
|
}
|
|
|
|
func (b *localController) DisconnectProcess(ctx context.Context, ref, pid string) error {
|
|
if ref != b.ref {
|
|
return errors.Errorf("unknown ref %q", ref)
|
|
}
|
|
return b.processes.DeleteProcess(pid)
|
|
}
|
|
|
|
func (b *localController) cancelRunningProcesses() {
|
|
b.processes.CancelRunningProcesses()
|
|
}
|
|
|
|
func (b *localController) Invoke(ctx context.Context, ref string, pid string, cfg *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
|
|
if ref != b.ref {
|
|
return errors.Errorf("unknown ref %q", ref)
|
|
}
|
|
|
|
proc, ok := b.processes.Get(pid)
|
|
if !ok {
|
|
// Start a new process.
|
|
if b.buildConfig.resultCtx == nil {
|
|
return errors.New("no build result is registered")
|
|
}
|
|
var err error
|
|
proc, err = b.processes.StartProcess(pid, b.buildConfig.resultCtx, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Attach containerIn to this process
|
|
ioCancelledCh := make(chan struct{})
|
|
proc.ForwardIO(&ioset.In{Stdin: ioIn, Stdout: ioOut, Stderr: ioErr}, func() { close(ioCancelledCh) })
|
|
|
|
select {
|
|
case <-ioCancelledCh:
|
|
return errors.Errorf("io cancelled")
|
|
case err := <-proc.Done():
|
|
return err
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
}
|
|
}
|
|
|
|
func (b *localController) Kill(context.Context) error {
|
|
b.Close()
|
|
return nil
|
|
}
|
|
|
|
func (b *localController) Close() error {
|
|
b.cancelRunningProcesses()
|
|
if b.buildConfig.resultCtx != nil {
|
|
b.buildConfig.resultCtx.Done()
|
|
}
|
|
// TODO: cancel ongoing builds?
|
|
return nil
|
|
}
|
|
|
|
func (b *localController) List(ctx context.Context) (res []string, _ error) {
|
|
return []string{b.ref}, nil
|
|
}
|
|
|
|
func (b *localController) Disconnect(ctx context.Context, key string) error {
|
|
b.Close()
|
|
return nil
|
|
}
|
|
|
|
func (b *localController) Inspect(ctx context.Context, ref string) (*controllerapi.InspectResponse, error) {
|
|
if ref != b.ref {
|
|
return nil, errors.Errorf("unknown ref %q", ref)
|
|
}
|
|
return &controllerapi.InspectResponse{Options: b.buildConfig.buildOptions}, nil
|
|
}
|