github.com/pdmccormick/importable-docker-buildx@v0.0.0-20240426161518-e47091289030/commands/debug/root.go (about)

     1  package debug
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"runtime"
     7  
     8  	"github.com/containerd/console"
     9  	"github.com/docker/buildx/controller"
    10  	"github.com/docker/buildx/controller/control"
    11  	controllerapi "github.com/docker/buildx/controller/pb"
    12  	"github.com/docker/buildx/monitor"
    13  	"github.com/docker/buildx/util/cobrautil"
    14  	"github.com/docker/buildx/util/progress"
    15  	"github.com/docker/cli/cli/command"
    16  	"github.com/moby/buildkit/util/progress/progressui"
    17  	"github.com/pkg/errors"
    18  	"github.com/sirupsen/logrus"
    19  	"github.com/spf13/cobra"
    20  )
    21  
    22  // DebugConfig is a user-specified configuration for the debugger.
    23  type DebugConfig struct {
    24  	// InvokeFlag is a flag to configure the launched debugger and the commaned executed on the debugger.
    25  	InvokeFlag string
    26  
    27  	// OnFlag is a flag to configure the timing of launching the debugger.
    28  	OnFlag string
    29  }
    30  
    31  // DebuggableCmd is a command that supports debugger with recognizing the user-specified DebugConfig.
    32  type DebuggableCmd interface {
    33  	// NewDebugger returns the new *cobra.Command with support for the debugger with recognizing DebugConfig.
    34  	NewDebugger(*DebugConfig) *cobra.Command
    35  }
    36  
    37  func RootCmd(dockerCli command.Cli, children ...DebuggableCmd) *cobra.Command {
    38  	var controlOptions control.ControlOptions
    39  	var progressMode string
    40  	var options DebugConfig
    41  
    42  	cmd := &cobra.Command{
    43  		Use:   "debug",
    44  		Short: "Start debugger",
    45  		Args:  cobra.NoArgs,
    46  		RunE: func(cmd *cobra.Command, args []string) error {
    47  			printer, err := progress.NewPrinter(context.TODO(), os.Stderr, progressui.DisplayMode(progressMode))
    48  			if err != nil {
    49  				return err
    50  			}
    51  
    52  			ctx := context.TODO()
    53  			c, err := controller.NewController(ctx, controlOptions, dockerCli, printer)
    54  			if err != nil {
    55  				return err
    56  			}
    57  			defer func() {
    58  				if err := c.Close(); err != nil {
    59  					logrus.Warnf("failed to close server connection %v", err)
    60  				}
    61  			}()
    62  			con := console.Current()
    63  			if err := con.SetRaw(); err != nil {
    64  				return errors.Errorf("failed to configure terminal: %v", err)
    65  			}
    66  
    67  			_, err = monitor.RunMonitor(ctx, "", nil, controllerapi.InvokeConfig{
    68  				Tty: true,
    69  			}, c, dockerCli.In(), os.Stdout, os.Stderr, printer)
    70  			con.Reset()
    71  			return err
    72  		},
    73  	}
    74  	cobrautil.MarkCommandExperimental(cmd)
    75  
    76  	flags := cmd.Flags()
    77  	flags.StringVar(&options.InvokeFlag, "invoke", "", "Launch a monitor with executing specified command")
    78  	flags.StringVar(&options.OnFlag, "on", "error", "When to launch the monitor ([always, error])")
    79  
    80  	flags.StringVar(&controlOptions.Root, "root", "", "Specify root directory of server to connect for the monitor")
    81  	flags.BoolVar(&controlOptions.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server for the monitor (supported only on linux)")
    82  	flags.StringVar(&controlOptions.ServerConfig, "server-config", "", "Specify buildx server config file for the monitor (used only when launching new server)")
    83  	flags.StringVar(&progressMode, "progress", "auto", `Set type of progress output ("auto", "plain", "tty") for the monitor. Use plain to show container output`)
    84  
    85  	cobrautil.MarkFlagsExperimental(flags, "invoke", "on", "root", "detach", "server-config")
    86  
    87  	for _, c := range children {
    88  		cmd.AddCommand(c.NewDebugger(&options))
    89  	}
    90  
    91  	return cmd
    92  }