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 }