github.com/rakutentech/cli@v6.12.5-0.20151006231303-24468b65536e+incompatible/plugin_examples/README.md (about) 1 # Changes in v6.12.0 2 - New API: 3 ```go 4 GetApp(string) (plugin_models.GetAppModel, error) 5 GetApps() ([]plugin_models.GetAppsModel, error) 6 GetOrgs() ([]plugin_models.GetOrgs_Model, error) 7 GetSpaces() ([]plugin_models.GetSpaces_Model, error) 8 GetOrgUsers(string, ...string) ([]plugin_models.GetOrgUsers_Model, error) 9 GetSpaceUsers(string, string) ([]plugin_models.GetSpaceUsers_Model, error) 10 GetServices() ([]plugin_models.GetServices_Model, error) 11 GetService(string) (plugin_models.GetService_Model, error) 12 GetOrg(string) (plugin_models.GetOrg_Model, error) 13 GetSpace(string) (plugin_models.GetSpace_Model, error) 14 ``` 15 - Allow minimum CLI version required to be specified in plugin. Example: 16 ```go 17 func (c *cmd) GetMetadata() plugin.PluginMetadata { 18 return plugin.PluginMetadata{ 19 Name: "Test1", 20 MinCliVersion: plugin.VersionType{ 21 Major: 6, 22 Minor: 12, 23 Build: 0, 24 }, 25 } 26 } 27 ``` 28 29 30 [Complete change log ...](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/CHANGELOG.md) 31 32 # Developing a Plugin 33 [Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/DOC.md) 34 35 This README discusses how to develop a cf CLI plugin. 36 For user-focused documentation, see [Using the cf CLI](http://docs.cloudfoundry.org/devguide/installcf/use-cli-plugins.html). 37 38 *If you wish to share your plugin with the community, see [here](http://github.com/cloudfoundry-incubator/cli-plugin-repo) for plugin submission. 39 40 41 ## Development Requirements 42 43 - Golang installed 44 - Tagged version of CLI release source code that supports plugins; cf CLI v.6.7.0 and above 45 46 ## Architecture Overview 47 48 The cf CLI plugin architecture model follows the remote procedure call (RPC) model. 49 The cf CLI invokes each plugin, runs it as an independent executable, and handles all start, stop, and clean up tasks for plugin executable resources. 50 51 Here is an illustration of the workflow when a plugin command is being invoked. 52 53 1: CLI launches 2 processes, the rpc server and the independent plugin executable 54 <p align="center"> 55 <img src="https://raw.githubusercontent.com/cloudfoundry/cli/master/plugin_examples/images/rpc_flow1.png" alt="workflow 1" width="400px"> 56 </p> 57 58 2: Plugin establishes a connection to the RPC server, the connection is used to invoke core cli commands. 59 <p align="center"> 60 <img src="https://raw.githubusercontent.com/cloudfoundry/cli/master/plugin_examples/images/rpc_flow2.png" alt="workflow 1" width="400px"> 61 </p> 62 63 3: When a plugin invokes a cli command, it talks to the rpc server, and the rpc server interacts with cf cli to perform the command. The result is passed back to the plugin through the rpc server. 64 <p align="center"> 65 <img src="https://raw.githubusercontent.com/cloudfoundry/cli/master/plugin_examples/images/rpc_flow3.png" alt="workflow 1" width="400px"> 66 </p> 67 68 - Plugins that you develop for the cf CLI must conform to a predefined plugin interface that we discuss below. 69 70 ## Writing a Plugin 71 72 [Go here for documentation of the plugin API](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/DOC.md) 73 74 To write a plugin for the cf CLI, implement the 75 [predefined plugin interface](https://github.com/cloudfoundry/cli/blob/master/plugin/plugin.go). 76 77 The interface uses a `Run(...)` method as the main entry point between the CLI 78 and a plugin. This method receives the following arguments: 79 80 - A struct `plugin.CliConnection` that contains methods for invoking cf CLI commands 81 - A string array that contains the arguments passed from the `cf` process 82 83 The `GetMetadata()` function informs the CLI of the name of a plugin, plugin version (optional), minimum Cli version required (optional), the commands it implements, and help text for each command that users can display 84 with `cf help`. 85 86 To initialize a plugin, call `plugin.Start(new(MyPluginStruct))` from within the `main()` method of your plugin. The `plugin.Start(...)` function requires a new reference to the struct that implements the defined interface. 87 88 This repo contains a basic plugin example [here](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/basic_plugin.go).<br> 89 To see more examples, go [here](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/). 90 91 If you wish to employ TDD in your plugin development, [here](https://github.com/cloudfoundry/cli/tree/master/plugin_examples/call_cli_cmd/main) is an example of a plugin that calls core cli command with the use of `FakeCliConnection` for testing. 92 93 ### Using Command Line Arguments 94 95 The `Run(...)` method accepts the command line arguments and flags that you 96 define for a plugin. 97 98 See the [command line arguments example] (https://github.com/cloudfoundry/cli/blob/master/plugin_examples/echo.go) included in this repo. 99 100 ### Calling CLI Commands 101 102 You can invoke CLI commands with `cliConnection.CliCommand([]args)` from 103 within a plugin's `Run(...)` method. The `Run(...)` method receives the 104 `cliConnection` as its first argument. 105 106 The `cliConnection.CliCommand([]args)` returns the output printed by the command and an error. The output is returned as a slice of strings. The error 107 will be present if the call to the CLI command fails. 108 109 See the [calling CLI commands example](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/call_cli_cmd/main/call_cli_cmd.go) included in this repo. 110 111 ### Creating Interactive Plugins 112 113 Because a plugin has access to stdin during a call to the `Run(...)` method, you can create interactive plugins. See the [interactive plugin example](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/interactive.go) 114 included in this repo. 115 116 ### Creating Plugins with multiple commands 117 118 A single plugin binary can have more than one command, and each command can have it's own help text defined. For an example of multi-comamnd plugins, see the [multiple commands example](https://github.com/cloudfoundry/cli/blob/master/plugin_examples/multiple_commands.go) 119 120 ### Notification upon uninstalling 121 122 When a user calls the `cf uninstall-plugin` command, CLI notifies the plugin via a call with 'CLI-MESSAGE-UNINSTALL' as the first item in `[]args` from within the plugin's `Run(...)` method. 123 124 ### Enforcing a minimum CLI version required for the plugin. 125 126 ```go 127 func (c *cmd) GetMetadata() plugin.PluginMetadata { 128 return plugin.PluginMetadata{ 129 Name: "Test1", 130 MinCliVersion: plugin.VersionType{ 131 Major: 6, 132 Minor: 12, 133 Build: 0, 134 }, 135 } 136 } 137 ``` 138 139 ## Compiling Plugin Source Code 140 141 The cf CLI requires an executable file to install the plugin. You must compile the source code with the `go build` command before distributing the plugin, or instruct your users to compile the plugin source code before 142 installing the plugin. For information about compiling Go source code, see [Compile packages and dependencies](https://golang.org/cmd/go/). 143 144 ## Using Plugins 145 146 After you compile a plugin, use the following commands to install and manage the plugin. 147 148 ### Installing Plugins 149 150 To install a plugin, run: 151 152 `cf install-plugin PATH_TO_PLUGIN_BINARY` 153 154 ### Listing Plugins 155 156 To display a list of installed plugins and the commands available from each plugin, run: 157 158 `cf plugins` 159 160 ### Uninstalling Plugins 161 162 To remove a plugin, run: 163 164 `cf uninstall-plugin PLUGIN_NAME` 165 166 ## Known Issues 167 168 - When invoking a CLI command using `cliConnection.CliCommand([]args)` a plugin developer will not receive output generated by the codegangsta/cli package. This includes usage failures when executing a cli command, `cf help`, or `cli SOME-COMMAND -h`. 169 - Due to architectural limitations, calling CLI core commands is not concurrency-safe. The correct execution of concurrent commands is not guaranteed. An architecture restructuring is in the works to fix this in the near future. 170 171