github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/plugin/rpc/cli_rpc_server.go (about)

     1  package rpc
     2  
     3  import (
     4  	"os"
     5  
     6  	"github.com/cloudfoundry/cli/cf"
     7  	"github.com/cloudfoundry/cli/cf/api"
     8  	"github.com/cloudfoundry/cli/cf/command_registry"
     9  	"github.com/cloudfoundry/cli/cf/configuration/core_config"
    10  	"github.com/cloudfoundry/cli/cf/terminal"
    11  	"github.com/cloudfoundry/cli/plugin"
    12  	"github.com/cloudfoundry/cli/plugin/models"
    13  	"github.com/cloudfoundry/cli/utils"
    14  
    15  	"fmt"
    16  	"net"
    17  	"net/rpc"
    18  	"strconv"
    19  )
    20  
    21  type CliRpcService struct {
    22  	listener net.Listener
    23  	stopCh   chan struct{}
    24  	Pinged   bool
    25  	RpcCmd   *CliRpcCmd
    26  }
    27  
    28  type CliRpcCmd struct {
    29  	PluginMetadata       *plugin.PluginMetadata
    30  	outputCapture        terminal.OutputCapture
    31  	terminalOutputSwitch terminal.TerminalOutputSwitch
    32  	cliConfig            core_config.Repository
    33  	repoLocator          api.RepositoryLocator
    34  	newCmdRunner         NonCodegangstaRunner
    35  	outputBucket         *[]string
    36  }
    37  
    38  func NewRpcService(outputCapture terminal.OutputCapture, terminalOutputSwitch terminal.TerminalOutputSwitch, cliConfig core_config.Repository, repoLocator api.RepositoryLocator, newCmdRunner NonCodegangstaRunner) (*CliRpcService, error) {
    39  	rpcService := &CliRpcService{
    40  		RpcCmd: &CliRpcCmd{
    41  			PluginMetadata:       &plugin.PluginMetadata{},
    42  			outputCapture:        outputCapture,
    43  			terminalOutputSwitch: terminalOutputSwitch,
    44  			cliConfig:            cliConfig,
    45  			repoLocator:          repoLocator,
    46  			newCmdRunner:         newCmdRunner,
    47  		},
    48  	}
    49  
    50  	err := rpc.Register(rpcService.RpcCmd)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	return rpcService, nil
    56  }
    57  
    58  func (cli *CliRpcService) Stop() {
    59  	close(cli.stopCh)
    60  	cli.listener.Close()
    61  }
    62  
    63  func (cli *CliRpcService) Port() string {
    64  	return strconv.Itoa(cli.listener.Addr().(*net.TCPAddr).Port)
    65  }
    66  
    67  func (cli *CliRpcService) Start() error {
    68  	var err error
    69  
    70  	cli.stopCh = make(chan struct{})
    71  
    72  	cli.listener, err = net.Listen("tcp", "127.0.0.1:0")
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	go func() {
    78  		for {
    79  			conn, err := cli.listener.Accept()
    80  			if err != nil {
    81  				select {
    82  				case <-cli.stopCh:
    83  					return
    84  				default:
    85  					fmt.Println(err)
    86  				}
    87  			} else {
    88  				go rpc.ServeConn(conn)
    89  			}
    90  		}
    91  	}()
    92  
    93  	return nil
    94  }
    95  
    96  func (cmd *CliRpcCmd) IsMinCliVersion(version string, retVal *bool) error {
    97  	if cf.Version == "BUILT_FROM_SOURCE" {
    98  		*retVal = true
    99  	} else {
   100  		curVersion := utils.NewVersion(cf.Version)
   101  		requiredVersion := utils.NewVersion(version)
   102  		*retVal = curVersion.GreaterThanOrEqual(requiredVersion)
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  func (cmd *CliRpcCmd) SetPluginMetadata(pluginMetadata plugin.PluginMetadata, retVal *bool) error {
   109  	cmd.PluginMetadata = &pluginMetadata
   110  	*retVal = true
   111  	return nil
   112  }
   113  
   114  func (cmd *CliRpcCmd) DisableTerminalOutput(disable bool, retVal *bool) error {
   115  	cmd.terminalOutputSwitch.DisableTerminalOutput(disable)
   116  	*retVal = true
   117  	return nil
   118  }
   119  
   120  func (cmd *CliRpcCmd) CallCoreCommand(args []string, retVal *bool) error {
   121  	defer func() {
   122  		recover()
   123  	}()
   124  
   125  	var err error
   126  	cmdRegistry := command_registry.Commands
   127  
   128  	cmd.outputBucket = &[]string{}
   129  	cmd.outputCapture.SetOutputBucket(cmd.outputBucket)
   130  
   131  	if cmdRegistry.CommandExists(args[0]) {
   132  		deps := command_registry.NewDependency()
   133  
   134  		//set deps objs to be the one used by all other codegangsta commands
   135  		//once all commands are converted, we can make fresh deps for each command run
   136  		deps.Config = cmd.cliConfig
   137  		deps.RepoLocator = cmd.repoLocator
   138  
   139  		//set command ui's TeePrinter to be the one used by RpcService, for output to be captured
   140  		deps.Ui = terminal.NewUI(os.Stdin, cmd.outputCapture.(*terminal.TeePrinter))
   141  
   142  		err = cmd.newCmdRunner.Command(args, deps, false)
   143  	} else {
   144  		*retVal = false
   145  		return nil
   146  	}
   147  
   148  	if err != nil {
   149  		*retVal = false
   150  		return err
   151  	}
   152  
   153  	*retVal = true
   154  	return nil
   155  }
   156  
   157  func (cmd *CliRpcCmd) GetOutputAndReset(args bool, retVal *[]string) error {
   158  	*retVal = *cmd.outputBucket
   159  	return nil
   160  }
   161  
   162  func (cmd *CliRpcCmd) GetCurrentOrg(args string, retVal *plugin_models.Organization) error {
   163  	retVal.Name = cmd.cliConfig.OrganizationFields().Name
   164  	retVal.Guid = cmd.cliConfig.OrganizationFields().Guid
   165  	return nil
   166  }
   167  
   168  func (cmd *CliRpcCmd) GetCurrentSpace(args string, retVal *plugin_models.Space) error {
   169  	retVal.Name = cmd.cliConfig.SpaceFields().Name
   170  	retVal.Guid = cmd.cliConfig.SpaceFields().Guid
   171  
   172  	return nil
   173  }
   174  
   175  func (cmd *CliRpcCmd) Username(args string, retVal *string) error {
   176  	*retVal = cmd.cliConfig.Username()
   177  
   178  	return nil
   179  }
   180  
   181  func (cmd *CliRpcCmd) UserGuid(args string, retVal *string) error {
   182  	*retVal = cmd.cliConfig.UserGuid()
   183  
   184  	return nil
   185  }
   186  
   187  func (cmd *CliRpcCmd) UserEmail(args string, retVal *string) error {
   188  	*retVal = cmd.cliConfig.UserEmail()
   189  
   190  	return nil
   191  }
   192  
   193  func (cmd *CliRpcCmd) IsLoggedIn(args string, retVal *bool) error {
   194  	*retVal = cmd.cliConfig.IsLoggedIn()
   195  
   196  	return nil
   197  }
   198  
   199  func (cmd *CliRpcCmd) IsSSLDisabled(args string, retVal *bool) error {
   200  	*retVal = cmd.cliConfig.IsSSLDisabled()
   201  
   202  	return nil
   203  }
   204  
   205  func (cmd *CliRpcCmd) HasOrganization(args string, retVal *bool) error {
   206  	*retVal = cmd.cliConfig.HasOrganization()
   207  
   208  	return nil
   209  }
   210  
   211  func (cmd *CliRpcCmd) HasSpace(args string, retVal *bool) error {
   212  	*retVal = cmd.cliConfig.HasSpace()
   213  
   214  	return nil
   215  }
   216  
   217  func (cmd *CliRpcCmd) ApiEndpoint(args string, retVal *string) error {
   218  	*retVal = cmd.cliConfig.ApiEndpoint()
   219  
   220  	return nil
   221  }
   222  
   223  func (cmd *CliRpcCmd) HasAPIEndpoint(args string, retVal *bool) error {
   224  	*retVal = cmd.cliConfig.HasAPIEndpoint()
   225  
   226  	return nil
   227  }
   228  
   229  func (cmd *CliRpcCmd) ApiVersion(args string, retVal *string) error {
   230  	*retVal = cmd.cliConfig.ApiVersion()
   231  
   232  	return nil
   233  }
   234  
   235  func (cmd *CliRpcCmd) LoggregatorEndpoint(args string, retVal *string) error {
   236  	*retVal = cmd.cliConfig.LoggregatorEndpoint()
   237  
   238  	return nil
   239  }
   240  
   241  func (cmd *CliRpcCmd) DopplerEndpoint(args string, retVal *string) error {
   242  	*retVal = cmd.cliConfig.DopplerEndpoint()
   243  
   244  	return nil
   245  }
   246  
   247  func (cmd *CliRpcCmd) AccessToken(args string, retVal *string) error {
   248  	*retVal = cmd.cliConfig.AccessToken()
   249  
   250  	return nil
   251  }
   252  
   253  func (cmd *CliRpcCmd) GetApp(appName string, retVal *plugin_models.GetAppModel) error {
   254  	defer func() {
   255  		recover()
   256  	}()
   257  
   258  	deps := command_registry.NewDependency()
   259  
   260  	//set deps objs to be the one used by all other codegangsta commands
   261  	//once all commands are converted, we can make fresh deps for each command run
   262  	deps.Config = cmd.cliConfig
   263  	deps.RepoLocator = cmd.repoLocator
   264  	deps.PluginModels.Application = retVal
   265  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   266  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   267  
   268  	return cmd.newCmdRunner.Command([]string{"app", appName}, deps, true)
   269  }
   270  
   271  func (cmd *CliRpcCmd) GetApps(_ string, retVal *[]plugin_models.GetAppsModel) error {
   272  	defer func() {
   273  		recover()
   274  	}()
   275  
   276  	deps := command_registry.NewDependency()
   277  
   278  	//set deps objs to be the one used by all other codegangsta commands
   279  	//once all commands are converted, we can make fresh deps for each command run
   280  	deps.Config = cmd.cliConfig
   281  	deps.RepoLocator = cmd.repoLocator
   282  	deps.PluginModels.AppsSummary = retVal
   283  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   284  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   285  
   286  	return cmd.newCmdRunner.Command([]string{"apps"}, deps, true)
   287  }
   288  
   289  func (cmd *CliRpcCmd) GetOrgs(_ string, retVal *[]plugin_models.GetOrgs_Model) error {
   290  	defer func() {
   291  		recover()
   292  	}()
   293  
   294  	deps := command_registry.NewDependency()
   295  
   296  	//set deps objs to be the one used by all other codegangsta commands
   297  	//once all commands are converted, we can make fresh deps for each command run
   298  	deps.Config = cmd.cliConfig
   299  	deps.RepoLocator = cmd.repoLocator
   300  	deps.PluginModels.Organizations = retVal
   301  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   302  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   303  
   304  	return cmd.newCmdRunner.Command([]string{"orgs"}, deps, true)
   305  }
   306  
   307  func (cmd *CliRpcCmd) GetSpaces(_ string, retVal *[]plugin_models.GetSpaces_Model) error {
   308  	defer func() {
   309  		recover()
   310  	}()
   311  
   312  	deps := command_registry.NewDependency()
   313  
   314  	//set deps objs to be the one used by all other codegangsta commands
   315  	//once all commands are converted, we can make fresh deps for each command run
   316  	deps.Config = cmd.cliConfig
   317  	deps.RepoLocator = cmd.repoLocator
   318  	deps.PluginModels.Spaces = retVal
   319  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   320  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   321  
   322  	return cmd.newCmdRunner.Command([]string{"spaces"}, deps, true)
   323  }
   324  
   325  func (cmd *CliRpcCmd) GetServices(_ string, retVal *[]plugin_models.GetServices_Model) error {
   326  	defer func() {
   327  		recover()
   328  	}()
   329  
   330  	deps := command_registry.NewDependency()
   331  
   332  	//set deps objs to be the one used by all other codegangsta commands
   333  	//once all commands are converted, we can make fresh deps for each command run
   334  	deps.Config = cmd.cliConfig
   335  	deps.RepoLocator = cmd.repoLocator
   336  	deps.PluginModels.Services = retVal
   337  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   338  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   339  
   340  	return cmd.newCmdRunner.Command([]string{"services"}, deps, true)
   341  }
   342  
   343  func (cmd *CliRpcCmd) GetOrgUsers(args []string, retVal *[]plugin_models.GetOrgUsers_Model) error {
   344  	defer func() {
   345  		recover()
   346  	}()
   347  
   348  	deps := command_registry.NewDependency()
   349  
   350  	//set deps objs to be the one used by all other codegangsta commands
   351  	//once all commands are converted, we can make fresh deps for each command run
   352  	deps.Config = cmd.cliConfig
   353  	deps.RepoLocator = cmd.repoLocator
   354  	deps.PluginModels.OrgUsers = retVal
   355  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   356  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   357  
   358  	return cmd.newCmdRunner.Command(append([]string{"org-users"}, args...), deps, true)
   359  }
   360  
   361  func (cmd *CliRpcCmd) GetSpaceUsers(args []string, retVal *[]plugin_models.GetSpaceUsers_Model) error {
   362  	defer func() {
   363  		recover()
   364  	}()
   365  
   366  	deps := command_registry.NewDependency()
   367  
   368  	//set deps objs to be the one used by all other codegangsta commands
   369  	//once all commands are converted, we can make fresh deps for each command run
   370  	deps.Config = cmd.cliConfig
   371  	deps.RepoLocator = cmd.repoLocator
   372  	deps.PluginModels.SpaceUsers = retVal
   373  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   374  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   375  
   376  	return cmd.newCmdRunner.Command(append([]string{"space-users"}, args...), deps, true)
   377  }
   378  
   379  func (cmd *CliRpcCmd) GetOrg(orgName string, retVal *plugin_models.GetOrg_Model) error {
   380  	defer func() {
   381  		recover()
   382  	}()
   383  
   384  	deps := command_registry.NewDependency()
   385  
   386  	//set deps objs to be the one used by all other codegangsta commands
   387  	//once all commands are converted, we can make fresh deps for each command run
   388  	deps.Config = cmd.cliConfig
   389  	deps.RepoLocator = cmd.repoLocator
   390  	deps.PluginModels.Organization = retVal
   391  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   392  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   393  
   394  	return cmd.newCmdRunner.Command([]string{"org", orgName}, deps, true)
   395  }
   396  
   397  func (cmd *CliRpcCmd) GetSpace(spaceName string, retVal *plugin_models.GetSpace_Model) error {
   398  	defer func() {
   399  		recover()
   400  	}()
   401  
   402  	deps := command_registry.NewDependency()
   403  
   404  	//set deps objs to be the one used by all other codegangsta commands
   405  	//once all commands are converted, we can make fresh deps for each command run
   406  	deps.Config = cmd.cliConfig
   407  	deps.RepoLocator = cmd.repoLocator
   408  	deps.PluginModels.Space = retVal
   409  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   410  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   411  
   412  	return cmd.newCmdRunner.Command([]string{"space", spaceName}, deps, true)
   413  }
   414  
   415  func (cmd *CliRpcCmd) GetService(serviceInstance string, retVal *plugin_models.GetService_Model) error {
   416  	defer func() {
   417  		recover()
   418  	}()
   419  
   420  	deps := command_registry.NewDependency()
   421  
   422  	//set deps objs to be the one used by all other codegangsta commands
   423  	//once all commands are converted, we can make fresh deps for each command run
   424  	deps.Config = cmd.cliConfig
   425  	deps.RepoLocator = cmd.repoLocator
   426  	deps.PluginModels.Service = retVal
   427  	cmd.terminalOutputSwitch.DisableTerminalOutput(true)
   428  	deps.Ui = terminal.NewUI(os.Stdin, cmd.terminalOutputSwitch.(*terminal.TeePrinter))
   429  
   430  	return cmd.newCmdRunner.Command([]string{"service", serviceInstance}, deps, true)
   431  }