github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/monitor/commands/attach.go (about) 1 package commands 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 8 "github.com/docker/buildx/monitor/types" 9 "github.com/pkg/errors" 10 ) 11 12 type AttachCmd struct { 13 m types.Monitor 14 15 stdout io.WriteCloser 16 } 17 18 func NewAttachCmd(m types.Monitor, stdout io.WriteCloser) types.Command { 19 return &AttachCmd{m, stdout} 20 } 21 22 func (cm *AttachCmd) Info() types.CommandInfo { 23 return types.CommandInfo{ 24 Name: "attach", 25 HelpMessage: "attach to a buildx server or a process in the container", 26 HelpMessageLong: ` 27 Usage: 28 attach ID 29 30 ID is for a session (visible via list command) or a process (visible via ps command). 31 If you attached to a process, use Ctrl-a-c for switching the monitor to that process's STDIO. 32 `, 33 } 34 } 35 36 func (cm *AttachCmd) Exec(ctx context.Context, args []string) error { 37 if len(args) < 2 { 38 return errors.Errorf("ID of session or process must be passed") 39 } 40 ref := args[1] 41 var id string 42 43 isProcess, err := isProcessID(ctx, cm.m, ref) 44 if err == nil && isProcess { 45 cm.m.Attach(ctx, ref) 46 id = ref 47 } 48 if id == "" { 49 refs, err := cm.m.List(ctx) 50 if err != nil { 51 return errors.Errorf("failed to get the list of sessions: %v", err) 52 } 53 found := false 54 for _, s := range refs { 55 if s == ref { 56 found = true 57 break 58 } 59 } 60 if !found { 61 return errors.Errorf("unknown ID: %q", ref) 62 } 63 cm.m.Detach() // Finish existing attach 64 cm.m.AttachSession(ref) 65 } 66 fmt.Fprintf(cm.stdout, "Attached to process %q. Press Ctrl-a-c to switch to the new container\n", id) 67 return nil 68 } 69 70 func isProcessID(ctx context.Context, c types.Monitor, ref string) (bool, error) { 71 sid := c.AttachedSessionID() 72 if sid == "" { 73 return false, errors.Errorf("no attaching session") 74 } 75 infos, err := c.ListProcesses(ctx, sid) 76 if err != nil { 77 return false, err 78 } 79 for _, p := range infos { 80 if p.ProcessID == ref { 81 return true, nil 82 } 83 } 84 return false, nil 85 }