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

     1  package commands
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  
     8  	controllererrors "github.com/docker/buildx/controller/errdefs"
     9  	controllerapi "github.com/docker/buildx/controller/pb"
    10  	"github.com/docker/buildx/monitor/types"
    11  	"github.com/docker/buildx/util/progress"
    12  	"github.com/moby/buildkit/solver/errdefs"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  type ReloadCmd struct {
    17  	m types.Monitor
    18  
    19  	stdout   io.WriteCloser
    20  	progress *progress.Printer
    21  
    22  	options      *controllerapi.BuildOptions
    23  	invokeConfig controllerapi.InvokeConfig
    24  }
    25  
    26  func NewReloadCmd(m types.Monitor, stdout io.WriteCloser, progress *progress.Printer, options *controllerapi.BuildOptions, invokeConfig controllerapi.InvokeConfig) types.Command {
    27  	return &ReloadCmd{m, stdout, progress, options, invokeConfig}
    28  }
    29  
    30  func (cm *ReloadCmd) Info() types.CommandInfo {
    31  	return types.CommandInfo{
    32  		Name:        "reload",
    33  		HelpMessage: "reloads the context and build it",
    34  		HelpMessageLong: `
    35  Usage:
    36    reload
    37  `,
    38  	}
    39  }
    40  
    41  func (cm *ReloadCmd) Exec(ctx context.Context, args []string) error {
    42  	var bo *controllerapi.BuildOptions
    43  	if ref := cm.m.AttachedSessionID(); ref != "" {
    44  		// Rebuilding an existing session; Restore the build option used for building this session.
    45  		res, err := cm.m.Inspect(ctx, ref)
    46  		if err != nil {
    47  			fmt.Printf("failed to inspect the current build session: %v\n", err)
    48  		} else {
    49  			bo = res.Options
    50  		}
    51  	} else {
    52  		bo = cm.options
    53  	}
    54  	if bo == nil {
    55  		return errors.Errorf("no build option is provided")
    56  	}
    57  	if ref := cm.m.AttachedSessionID(); ref != "" {
    58  		if err := cm.m.Disconnect(ctx, ref); err != nil {
    59  			fmt.Println("disconnect error", err)
    60  		}
    61  	}
    62  	var resultUpdated bool
    63  	cm.progress.Unpause()
    64  	ref, _, err := cm.m.Build(ctx, *bo, nil, cm.progress) // TODO: support stdin, hold build ref
    65  	cm.progress.Pause()
    66  	if err != nil {
    67  		var be *controllererrors.BuildError
    68  		if errors.As(err, &be) {
    69  			ref = be.Ref
    70  			resultUpdated = true
    71  		} else {
    72  			fmt.Printf("failed to reload: %v\n", err)
    73  		}
    74  		// report error
    75  		for _, s := range errdefs.Sources(err) {
    76  			s.Print(cm.stdout)
    77  		}
    78  		fmt.Fprintf(cm.stdout, "ERROR: %v\n", err)
    79  	} else {
    80  		resultUpdated = true
    81  	}
    82  	cm.m.AttachSession(ref)
    83  	if resultUpdated {
    84  		// rollback the running container with the new result
    85  		id := cm.m.Rollback(ctx, cm.invokeConfig)
    86  		fmt.Fprintf(cm.stdout, "Interactive container was restarted with process %q. Press Ctrl-a-c to switch to the new container\n", id)
    87  	}
    88  	return nil
    89  }