# Generate CLI Client Tool
Generate a command line client tool for your server
(This is in alpha state and is under development)

* Generated CLI code is a wrapper of the generated client code, which reads command line options and args to construct appropriate parameters and send to the server.
* Based on [cobra framework](https://github.com/spf13/cobra), and [viper](https://github.com/spf13/viper).
* Support shell completions.
* For advanced example, see [dockerctl](https://github.com/go-swagger/dockerctl), a CLI generated using this for [docker engine](https://www.docker.com/)
## General Command Layout
* Root command manages global flags
* Each open-api tag is a sub-command under root command. In go-swagger it is called operation group.
* Each open-api operationId is a sub-command under the tag it belongs to.
    * Each path and query parameter is a command line flag.
    * Body parameter corresponds to a command line flag, as a json string.
    * Each field in body parameter is a command line flag, and this extends to sub-definitions recursively.
        * body parameter json string will be taken as base payload, which flags for body fields will overwrite.

# Todo List CLI App Example
CLI tool in this folder is generated using the same swagger.yaml as `examples/auto-configure`. We will run that server to test this cli executable.

## Getting Started
### Generate the code (optional)
Generate go-swagger command (optional for this example, since code is already generated and checked-in in repo):
```
$ swagger generate cli --target=examples/cli --spec=examples/cli/swagger.yml --cli-app-name todoctl
```
### Run the CLI program
#### Run the tool using go run
```
$ go run examples/cli/cmd/todoctl/main.go --debug --hostname localhost:12345 --x-todolist-token "example token" todos addOne --item.description "hi" --body "{}"
```
#### Build the executable and then run
```
$ go build -o examples/cli/cmd/todoctl/todoctl examples/cli/cmd/todoctl/main.go
$ ./examples/cli/cmd/todoctl/todoctl
```
### Shell Completion
Shell completion is supported via [cobra](https://github.com/spf13/cobra#generating-shell-completions). bash, zsh, fish, PowerShell completion script can be generated by the CLI executable. More technical details [here](https://github.com/spf13/cobra/blob/master/shell_completions.md).
For example, bash completion is generated like this to stdout:
```
$ ./examples/cli/cmd/todoctl/todo-cli completion bash
```
To use the completion, do the following:
```bash
# temporary completion in current shell
$ source <(./examples/cli/cmd/todoctl/todoctl completion bash)
# add completion permanently to your system
$ ./examples/cli/cmd/todoctl/todoctl completion bash > /etc/bash_completion.d/todoctl
```
### Help Message Example
* Help messages can be obtained as follows:
```bash
$ ./examples/cli/cmd/todoctl/todoctl --help
```
```bash
$ ./examples/cli/cmd/todoctl/todoctl todos updateOne --help
```
### Use config file to store common flag values
`hostname`, `scheme`, `base_path` (default: `/`), and auth tokens can be read from a config file, so that you do not need to enter it every time via command line.
For example, todo-cli config file looks like this:
```json
{
    "hostname":"localhost:12345",
    "scheme":"http",
    "base_path":"/base-path/",
    "x-todolist-token":"example token"
}
```
The default location that the CLI will look for config file is `~/.config/<program name>/config.json`. One can also specify a config file location via flag`--config`. One can use `yaml`,`env`, etc file types, and the CLI can parse them all. The config file is supported via [viper](https://github.com/spf13/viper).
With the above config file for todo-cli, one can invoke the command like this:
```bash
$ ./examples/cli/cmd/cli/todo-cli todos findTodos
```
## Exercise: Running CLI against auto-configure server
* Start the server
```
$ go run examples/auto-configure/cmd/a-to-do-list-application-server/main.go --port=12345
```
* Make request using the CLI tool (using another shell)
```
$ go run examples/cli/cmd/todoctl/main.go --hostname localhost:12345 --x-todolist-token "example token" todos addOne --item.description "hi" --body "{}"
{"description":"hi"}

$ go run examples/cli/cmd/todoctl/main.go --hostname localhost:12345 --x-todolist-token "example token" todos findTodos
[{"description":"hi"}]

$ go run examples/cli/cmd/todoctl/main.go --hostname localhost:12345 --x-todolist-token "example token" todos updateOne --id 1 --item.completed true --item.description "done"
{"code":404,"message":"Item with id 1 is not found"}
```

### Missing Features
* Array and maps in body (It is unclear how to support)
* Enums
    * In help message
    * In shell auto-complete
* Validate params before sending
