github.com/mutagen-io/mutagen@v0.18.0-rc1/cmd/mutagen/forward/terminate.go (about) 1 package forward 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 forwardingsvc "github.com/mutagen-io/mutagen/pkg/service/forwarding" 17 promptingsvc "github.com/mutagen-io/mutagen/pkg/service/prompting" 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 forwardingService := forwardingsvc.NewForwardingClient(daemonConnection) 41 request := &forwardingsvc.TerminateRequest{ 42 Prompter: prompter, 43 Selection: selection, 44 } 45 response, err := forwardingService.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 forwarding 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 }