github.com/mutagen-io/mutagen@v0.18.0-rc1/cmd/mutagen/sync/terminate.go (about)

     1  package sync
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/spf13/cobra"
     8  
     9  	"google.golang.org/grpc"
    10  
    11  	"github.com/mutagen-io/mutagen/cmd"
    12  	"github.com/mutagen-io/mutagen/cmd/mutagen/daemon"
    13  
    14  	"github.com/mutagen-io/mutagen/pkg/grpcutil"
    15  	"github.com/mutagen-io/mutagen/pkg/selection"
    16  	promptingsvc "github.com/mutagen-io/mutagen/pkg/service/prompting"
    17  	synchronizationsvc "github.com/mutagen-io/mutagen/pkg/service/synchronization"
    18  )
    19  
    20  // TerminateWithSelection is an orchestration convenience method that performs a
    21  // terminate operation using the provided daemon connection and session
    22  // selection.
    23  func TerminateWithSelection(
    24  	daemonConnection *grpc.ClientConn,
    25  	selection *selection.Selection,
    26  ) error {
    27  	// Initiate command line messaging.
    28  	statusLinePrinter := &cmd.StatusLinePrinter{}
    29  	promptingCtx, promptingCancel := context.WithCancel(context.Background())
    30  	prompter, promptingErrors, err := promptingsvc.Host(
    31  		promptingCtx, promptingsvc.NewPromptingClient(daemonConnection),
    32  		&cmd.StatusLinePrompter{Printer: statusLinePrinter}, false,
    33  	)
    34  	if err != nil {
    35  		promptingCancel()
    36  		return fmt.Errorf("unable to initiate prompting: %w", err)
    37  	}
    38  
    39  	// Perform the terminate operation, cancel prompting, and handle errors.
    40  	synchronizationService := synchronizationsvc.NewSynchronizationClient(daemonConnection)
    41  	request := &synchronizationsvc.TerminateRequest{
    42  		Prompter:  prompter,
    43  		Selection: selection,
    44  	}
    45  	response, err := synchronizationService.Terminate(context.Background(), request)
    46  	promptingCancel()
    47  	<-promptingErrors
    48  	if err != nil {
    49  		statusLinePrinter.BreakIfPopulated()
    50  		return grpcutil.PeelAwayRPCErrorLayer(err)
    51  	} else if err = response.EnsureValid(); err != nil {
    52  		statusLinePrinter.BreakIfPopulated()
    53  		return fmt.Errorf("invalid terminate response received: %w", err)
    54  	}
    55  
    56  	// Success.
    57  	statusLinePrinter.Clear()
    58  	return nil
    59  }
    60  
    61  // terminateMain is the entry point for the terminate command.
    62  func terminateMain(_ *cobra.Command, arguments []string) error {
    63  	// Create session selection specification.
    64  	selection := &selection.Selection{
    65  		All:            terminateConfiguration.all,
    66  		Specifications: arguments,
    67  		LabelSelector:  terminateConfiguration.labelSelector,
    68  	}
    69  	if err := selection.EnsureValid(); err != nil {
    70  		return fmt.Errorf("invalid session selection specification: %w", err)
    71  	}
    72  
    73  	// Connect to the daemon and defer closure of the connection.
    74  	daemonConnection, err := daemon.Connect(true, true)
    75  	if err != nil {
    76  		return fmt.Errorf("unable to connect to daemon: %w", err)
    77  	}
    78  	defer daemonConnection.Close()
    79  
    80  	// Perform the terminate operation.
    81  	return TerminateWithSelection(daemonConnection, selection)
    82  }
    83  
    84  // terminateCommand is the terminate command.
    85  var terminateCommand = &cobra.Command{
    86  	Use:          "terminate [<session>...]",
    87  	Short:        "Permanently terminate a synchronization session",
    88  	RunE:         terminateMain,
    89  	SilenceUsage: true,
    90  }
    91  
    92  // terminateConfiguration stores configuration for the terminate command.
    93  var terminateConfiguration struct {
    94  	// help indicates whether or not to show help information and exit.
    95  	help bool
    96  	// all indicates whether or not all sessions should be terminated.
    97  	all bool
    98  	// labelSelector encodes a label selector to be used in identifying which
    99  	// sessions should be paused.
   100  	labelSelector string
   101  }
   102  
   103  func init() {
   104  	// Grab a handle for the command line flags.
   105  	flags := terminateCommand.Flags()
   106  
   107  	// Disable alphabetical sorting of flags in help output.
   108  	flags.SortFlags = false
   109  
   110  	// Manually add a help flag to override the default message. Cobra will
   111  	// still implement its logic automatically.
   112  	flags.BoolVarP(&terminateConfiguration.help, "help", "h", false, "Show help information")
   113  
   114  	// Wire up terminate flags.
   115  	flags.BoolVarP(&terminateConfiguration.all, "all", "a", false, "Terminate all sessions")
   116  	flags.StringVar(&terminateConfiguration.labelSelector, "label-selector", "", "Terminate sessions matching the specified label selector")
   117  }