github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/command/plugin/shared/rpc.go (about)

     1  package shared
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"time"
     9  
    10  	netrpc "net/rpc"
    11  
    12  	"code.cloudfoundry.org/cli/cf/commandregistry"
    13  	"code.cloudfoundry.org/cli/cf/trace"
    14  	"code.cloudfoundry.org/cli/plugin/rpc"
    15  	"code.cloudfoundry.org/cli/util/configv3"
    16  )
    17  
    18  type Config interface {
    19  	DialTimeout() time.Duration
    20  	Verbose() (bool, []string)
    21  }
    22  
    23  type UI interface {
    24  	Writer() io.Writer
    25  }
    26  
    27  type RPCService struct {
    28  	config     Config
    29  	ui         UI
    30  	rpcService *rpc.CliRpcService
    31  }
    32  
    33  func NewRPCService(config Config, ui UI) (*RPCService, error) {
    34  	isVerbose, logFiles := config.Verbose()
    35  	traceLogger := trace.NewLogger(ui.Writer(), isVerbose, logFiles...)
    36  
    37  	deps := commandregistry.NewDependency(ui.Writer(), traceLogger, fmt.Sprint(config.DialTimeout().Seconds()))
    38  	defer deps.Config.Close()
    39  
    40  	server := netrpc.NewServer()
    41  	rpcService, err := rpc.NewRpcService(deps.TeePrinter, deps.TeePrinter, deps.Config, deps.RepoLocator, rpc.NewCommandRunner(), deps.Logger, ui.Writer(), server)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	return &RPCService{
    47  		config:     config,
    48  		ui:         ui,
    49  		rpcService: rpcService,
    50  	}, nil
    51  }
    52  
    53  func (r RPCService) Run(path string, command string) error {
    54  	err := r.rpcService.Start()
    55  	if err != nil {
    56  		return err
    57  	}
    58  	defer r.rpcService.Stop()
    59  
    60  	cmd := exec.Command(path, r.rpcService.Port(), command)
    61  	cmd.Stdout = os.Stdout
    62  	cmd.Stderr = os.Stderr
    63  
    64  	return cmd.Run()
    65  }
    66  
    67  func (r RPCService) GetMetadata(path string) (configv3.Plugin, error) {
    68  	err := r.Run(path, "SendMetadata")
    69  	if err != nil {
    70  		return configv3.Plugin{}, err
    71  	}
    72  
    73  	metadata := r.rpcService.RpcCmd.PluginMetadata
    74  	plugin := configv3.Plugin{
    75  		Name: metadata.Name,
    76  		Version: configv3.PluginVersion{
    77  			Major: metadata.Version.Major,
    78  			Minor: metadata.Version.Minor,
    79  			Build: metadata.Version.Build,
    80  		},
    81  		Commands: make([]configv3.PluginCommand, len(metadata.Commands)),
    82  	}
    83  
    84  	for i, command := range metadata.Commands {
    85  		plugin.Commands[i] = configv3.PluginCommand{
    86  			Name:     command.Name,
    87  			Alias:    command.Alias,
    88  			HelpText: command.HelpText,
    89  			UsageDetails: configv3.PluginUsageDetails{
    90  				Usage:   command.UsageDetails.Usage,
    91  				Options: command.UsageDetails.Options,
    92  			},
    93  		}
    94  	}
    95  
    96  	return plugin, nil
    97  }