diff --git a/monitor/commands/attach.go b/monitor/commands/attach.go index 959a1502..2de39e5f 100644 --- a/monitor/commands/attach.go +++ b/monitor/commands/attach.go @@ -58,7 +58,7 @@ func (cm *AttachCmd) Exec(ctx context.Context, args []string) error { } func isProcessID(ctx context.Context, c types.Monitor, ref string) (bool, error) { - infos, err := c.ListProcesses(ctx) + infos, err := c.ListProcesses(ctx, c.AttachedSessionID()) if err != nil { return false, err } diff --git a/monitor/commands/disconnect.go b/monitor/commands/disconnect.go index ce94f46f..582852b3 100644 --- a/monitor/commands/disconnect.go +++ b/monitor/commands/disconnect.go @@ -26,7 +26,7 @@ func (cm *DisconnectCmd) Exec(ctx context.Context, args []string) error { } isProcess, err := isProcessID(ctx, cm.m, target) if err == nil && isProcess { - if err := cm.m.DisconnectProcess(ctx, target); err != nil { + if err := cm.m.DisconnectProcess(ctx, cm.m.AttachedSessionID(), target); err != nil { return errors.Errorf("disconnecting from process failed %v", target) } return nil diff --git a/monitor/commands/ps.go b/monitor/commands/ps.go index 84808f99..39c2f2cc 100644 --- a/monitor/commands/ps.go +++ b/monitor/commands/ps.go @@ -23,7 +23,8 @@ func (cm *PsCmd) Info() types.CommandInfo { } func (cm *PsCmd) Exec(ctx context.Context, args []string) error { - plist, err := cm.m.ListProcesses(ctx) + ref := cm.m.AttachedSessionID() + plist, err := cm.m.ListProcesses(ctx, ref) if err != nil { return err } diff --git a/monitor/commands/reload.go b/monitor/commands/reload.go index 77764125..11dd4589 100644 --- a/monitor/commands/reload.go +++ b/monitor/commands/reload.go @@ -32,9 +32,9 @@ func (cm *ReloadCmd) Info() types.CommandInfo { func (cm *ReloadCmd) Exec(ctx context.Context, args []string) error { var bo *controllerapi.BuildOptions - if cm.m.AttachedSessionID() != "" { + if ref := cm.m.AttachedSessionID(); ref != "" { // Rebuilding an existing session; Restore the build option used for building this session. - res, err := cm.m.Inspect(ctx) + res, err := cm.m.Inspect(ctx, ref) if err != nil { fmt.Printf("failed to inspect the current build session: %v\n", err) } else { @@ -46,8 +46,8 @@ func (cm *ReloadCmd) Exec(ctx context.Context, args []string) error { if bo == nil { return errors.Errorf("no build option is provided") } - if cm.m.AttachedSessionID() != "" { - if err := cm.m.Disconnect(ctx); err != nil { + if ref := cm.m.AttachedSessionID(); ref != "" { + if err := cm.m.Disconnect(ctx, ref); err != nil { fmt.Println("disconnect error", err) } } diff --git a/monitor/monitor.go b/monitor/monitor.go index 2e00c8b4..78666e0e 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -17,7 +17,6 @@ import ( "github.com/docker/buildx/util/ioset" "github.com/docker/buildx/util/progress" "github.com/google/shlex" - "github.com/moby/buildkit/client" "github.com/moby/buildkit/identity" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -63,8 +62,8 @@ func RunMonitor(ctx context.Context, curRef string, options *controllerapi.Build invokeForwarder := ioset.NewForwarder() invokeForwarder.SetIn(&containerIn) m := &monitor{ - controllerRef: newControllerRef(c, curRef), - invokeIO: invokeForwarder, + BuildxController: c, + invokeIO: invokeForwarder, muxIO: ioset.NewMuxIO(ioset.In{ Stdin: io.NopCloser(stdin), Stdout: nopCloser{stdout}, @@ -77,6 +76,7 @@ func RunMonitor(ctx context.Context, curRef string, options *controllerapi.Build return "Switched IO\n" }), } + m.ref.Store(curRef) // Start container automatically fmt.Fprintf(stdout, "Launching interactive container. Press Ctrl-a-c to switch to monitor console\n") @@ -203,7 +203,8 @@ type readWriter struct { } type monitor struct { - *controllerRef + control.BuildxController + ref atomic.Value muxIO *ioset.MuxIO invokeIO *ioset.Forwarder @@ -212,15 +213,15 @@ type monitor struct { } func (m *monitor) DisconnectSession(ctx context.Context, targetID string) error { - return m.controllerRef.raw().Disconnect(ctx, targetID) + return m.Disconnect(ctx, targetID) } func (m *monitor) AttachSession(ref string) { - m.controllerRef.ref.Store(ref) + m.ref.Store(ref) } func (m *monitor) AttachedSessionID() string { - return m.controllerRef.ref.Load().(string) + return m.ref.Load().(string) } func (m *monitor) Rollback(ctx context.Context, cfg controllerapi.InvokeConfig) string { @@ -298,87 +299,12 @@ func (m *monitor) invoke(ctx context.Context, pid string, cfg controllerapi.Invo defer invokeCancelAndDetachFn() m.invokeCancel = invokeCancelAndDetachFn - err := m.controllerRef.invoke(invokeCtx, pid, cfg, containerIn.Stdin, containerIn.Stdout, containerIn.Stderr) + err := m.Invoke(invokeCtx, m.AttachedSessionID(), pid, cfg, containerIn.Stdin, containerIn.Stdout, containerIn.Stderr) close(waitInvokeDoneCh) return err } -func newControllerRef(c control.BuildxController, ref string) *controllerRef { - cr := &controllerRef{c: c} - cr.ref.Store(ref) - return cr -} - -type controllerRef struct { - c control.BuildxController - ref atomic.Value -} - -func (c *controllerRef) raw() control.BuildxController { - return c.c -} - -func (c *controllerRef) getRef() (string, error) { - ref := c.ref.Load() - if ref == "" { - return "", errors.Errorf("client is not attached to a session") - } - return ref.(string), nil -} - -func (c *controllerRef) Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, err error) { - return c.c.Build(ctx, options, in, progress) -} - -func (c *controllerRef) invoke(ctx context.Context, pid string, options controllerapi.InvokeConfig, ioIn io.ReadCloser, ioOut io.WriteCloser, ioErr io.WriteCloser) error { - ref, err := c.getRef() - if err != nil { - return err - } - return c.c.Invoke(ctx, ref, pid, options, ioIn, ioOut, ioErr) -} - -func (c *controllerRef) Kill(ctx context.Context) error { - return c.c.Kill(ctx) -} - -func (c *controllerRef) List(ctx context.Context) (refs []string, _ error) { - return c.c.List(ctx) -} - -func (c *controllerRef) ListProcesses(ctx context.Context) (infos []*controllerapi.ProcessInfo, retErr error) { - ref, err := c.getRef() - if err != nil { - return nil, err - } - return c.c.ListProcesses(ctx, ref) -} - -func (c *controllerRef) DisconnectProcess(ctx context.Context, pid string) error { - ref, err := c.getRef() - if err != nil { - return err - } - return c.c.DisconnectProcess(ctx, ref, pid) -} - -func (c *controllerRef) Inspect(ctx context.Context) (*controllerapi.InspectResponse, error) { - ref, err := c.getRef() - if err != nil { - return nil, err - } - return c.c.Inspect(ctx, ref) -} - -func (c *controllerRef) Disconnect(ctx context.Context) error { - ref, err := c.getRef() - if err != nil { - return err - } - return c.c.Disconnect(ctx, ref) -} - type nopCloser struct { io.Writer } diff --git a/monitor/types/types.go b/monitor/types/types.go index 60d92459..9efbcc15 100644 --- a/monitor/types/types.go +++ b/monitor/types/types.go @@ -2,15 +2,15 @@ package types import ( "context" - "io" + "github.com/docker/buildx/controller/control" controllerapi "github.com/docker/buildx/controller/pb" - "github.com/docker/buildx/util/progress" - "github.com/moby/buildkit/client" ) // Monitor provides APIs for attaching and controlling the buildx server. type Monitor interface { + control.BuildxController + // Rollback re-runs the interactive container with initial rootfs contents. Rollback(ctx context.Context, cfg controllerapi.InvokeConfig) string @@ -34,27 +34,6 @@ type Monitor interface { // AttachedSessionID returns the ID of the attached session. AttachedSessionID() string - - // Build executes the specified build and returns an ID of the session for debugging that build. - Build(ctx context.Context, options controllerapi.BuildOptions, in io.ReadCloser, progress progress.Writer) (ref string, resp *client.SolveResponse, err error) - - // Kill kills the buildx server. - Kill(ctx context.Context) error - - // List lists sessions. - List(ctx context.Context) (refs []string, _ error) - - // ListPrcesses lists processes in the attached session. - ListProcesses(ctx context.Context) (infos []*controllerapi.ProcessInfo, retErr error) - - // DisconnectProcess finishes the specified process. - DisconnectProcess(ctx context.Context, pid string) error - - // Inspect returns information about the attached build. - Inspect(ctx context.Context) (*controllerapi.InspectResponse, error) - - // Disconnect finishes the attached session. - Disconnect(ctx context.Context) error } // CommandInfo is information about a command.