mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-17 16:37:46 +08:00

Remove the controller grpc service along with associated code related to sessions or remote controllers. Data types that are still used with complicated dependency chains have been kept in the same package for a future refactor. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
124 lines
3.4 KiB
Go
124 lines
3.4 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/desktop"
|
|
"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) control.BuildxController {
|
|
return &localController{
|
|
dockerCli: dockerCli,
|
|
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 *cbuild.Options
|
|
}
|
|
|
|
type localController struct {
|
|
dockerCli command.Cli
|
|
buildConfig buildConfig
|
|
processes *processes.Manager
|
|
|
|
buildOnGoing atomic.Bool
|
|
}
|
|
|
|
func (b *localController) Build(ctx context.Context, options *cbuild.Options, in io.ReadCloser, progress progress.Writer) (*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 {
|
|
var ref string
|
|
var ebr *desktop.ErrorWithBuildRef
|
|
if errors.As(buildErr, &ebr) {
|
|
ref = ebr.Ref
|
|
}
|
|
buildErr = controllererrors.WrapBuild(buildErr, "", ref)
|
|
}
|
|
}
|
|
if buildErr != nil {
|
|
return nil, nil, buildErr
|
|
}
|
|
return resp, dockerfileMappings, nil
|
|
}
|
|
|
|
func (b *localController) ListProcesses(ctx context.Context) (infos []*processes.ProcessInfo, retErr error) {
|
|
return b.processes.ListProcesses(), nil
|
|
}
|
|
|
|
func (b *localController) DisconnectProcess(ctx context.Context, pid string) error {
|
|
return b.processes.DeleteProcess(pid)
|
|
}
|
|
|
|
func (b *localController) cancelRunningProcesses() {
|
|
b.processes.CancelRunningProcesses()
|
|
}
|
|
|
|
func (b *localController) Invoke(ctx context.Context, pid string, cfg *controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error {
|
|
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(error) { close(ioCancelledCh) })
|
|
|
|
select {
|
|
case <-ioCancelledCh:
|
|
return errors.Errorf("io cancelled")
|
|
case err := <-proc.Done():
|
|
return err
|
|
case <-ctx.Done():
|
|
return context.Cause(ctx)
|
|
}
|
|
}
|
|
|
|
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) Inspect(ctx context.Context) *cbuild.Options {
|
|
return b.buildConfig.buildOptions
|
|
}
|