GoogleCloudPlatform/kubernetes — pull request #1325 by ghodss (2014-09-16 00:47:57+00:00)
Title: Proposal for new kubecfg design (kubecfg2)

### Intent

The intent of this pull request is to propose a design for the present and future of kubecfg. The conversation from #1167 was the primary input into this design. The idea is to have kubecfg solve two use cases:

1. Provide a great user experience to view the current status of a Kubernetes cluster and to execute simple commands on the cluster.
1. Provide a tool which will accept configuration with generic resources to submit changes to and diff against a Kubernetes cluster.

The problem with the current design is that it is too generic to effectively support (1). The proposed redesign enables custom commands per resource (e.g. kubecfg pods, kubecfg services, etc.) but generic subcommands to satisfy (2) (kubecfg submit, kubecfg diff, kubecfg reconcile, etc.).

### Proposed set of subcommands

Note that only a few have been implemented so far in the attached commit.

* `kubecfg2` - Parent command.
* `pods`
* `list []` - List pods in a column-oriented view (see [Examples](#examples) below). By default, the first argument passed in acts as a filter by ID.
* `get ` - List info about a pod in a row-oriented view. Designed to show more metadata about a given pod, and over time can be enhanced to make navigating the cluster from a given pod very easy. Currently I'm adding a list of any replication controllers whose selectors match (and therefore who control) the selected pod.
* `delete ` - Delete a pod.
* `create ` - In theory this can come from stdin as well.
* `rc` - For replication controllers. Happy to use a different abbreviation but replicationControllers seemed too long.
* `list []`
* `get ` - RC's `get` command could become extremely rich. For now I've added Pods Status which queries for pods under this replication controller and shows counts for running, waiting and termianted, but in the future you could do diffs against the controller's PodTemplate and show counts for matching and non-matching pods. You could also show the first 3-4 pod ID's per category and then show , making debugging even easier.
* `delete ` - Straight REST delete without resizing first, as per current behavior.
* `create `
* `update `
* `set ` - A slightly more generic version of resize.
* `stop ` - First sets replicationController to 0, then deletes it, like the current kubecfg behavior.
* `rollingupdate ` - I've included this for parity but this is the one command that I don't think belongs in kubecfg ... it's too long-running, fraught with edge cases, and in reality would probably want to take more into consideration (like fluctuations in metrics, % of pods that come up successfully, etc.). I think this level of functionality belongs in an independent client that uses the API or kubecfg that can look at more components in the infrastructure than just kubernetes.
* `minions`
* `list []`
* `get `
* `services`
* `list []`
* `get `
* `resolve ` - Just an idea, but it could give you a random IP/port combination to connect to. May be useful for quickly locating a node to test for a given service.
* `submit [...]` - This command exists to satisfy the second use case above. Reconcile and submit any changes from a given set of config(s), from files or from stdin. If you had an entire directory tree of files that had configs that represented your cluster state, you could use this command to submit them all to either create or update your cluster.
* `diff [...]` - A dry-run version of `submit`.

### Examples

Here is what the current commit produces:

```
$ kubecfg2
kubecfg2 controls the Kubernetes cluster manager.

Find more information at https://github.com/GoogleCloudPlatform/kubernetes.

Usage:
kubecfg2 [command]

Available Commands:
version Print version of client and server
pods List, inspect and modify pods
rc List, inspect and modify replication controllers
help [command] Help about any command

Available Flags:
-a, --auth="/Users/sam/.kubernetes_auth": Path to the auth info file. If missing, prompt the user. Only used if doing https.
--help=false: help for kubecfg2
-h, --host="": Kubernetes apiserver to connect to
-m, --match-version=false: Require server version to match client version

Use "kubecfg2 help [command]" for more information about that command.

```
```
$ kubecfg2 help pods list
List one or more pods. Pass in an ID to filter.

Usage:
kubecfg2 pods list [] [flags]

Available Flags:
-a, --auth="/Users/sam/.kubernetes_auth": Path to the auth info file. If missing, prompt the user. Only used if doing https.
--help=false: help for list
-h, --host="": Kubernetes apiserver to connect to
-m, --match-version=false: Require server version to match client version
-l, --selector="": Selector (label query) to filter on

Use "kubecfg2 help [command]" for more information about that command.

```
```
$ kubecfg2 pods list
ID IMAGE(S) HOST LABELS STATUS
4893ea09-3d0d-11e4-b3ad-0800279696e1 dockerfile/nginx 127.0.0.1/ replicationController=MyNginxController Running
48943371-3d0d-11e4-b3ad-0800279696e1 dockerfile/nginx 127.0.0.1/ replicationController=MyNginxController Running
```
```
$ kubecfg2 pods list 4893ea09-3d0d-11e4-b3ad-0800279696e1
ID IMAGE(S) HOST LABELS STATUS
4893ea09-3d0d-11e4-b3ad-0800279696e1 dockerfile/nginx 127.0.0.1/ replicationController=MyNginxController Running
```
```
$ kubecfg2 pods get 4893ea09-3d0d-11e4-b3ad-0800279696e1
ID: 4893ea09-3d0d-11e4-b3ad-0800279696e1
Image(s): dockerfile/nginx
Host: 127.0.0.1/
Labels: replicationController=MyNginxController
Status: Running
Replication Controllers: MyNginxController (2/2 replicas created)
```
```
$ kubecfg2 rc list
ID IMAGE(S) SELECTOR REPLICAS
MyNginxController dockerfile/nginx replicationController=MyNginxController 2
```
```
$ kubecfg2 rc get MyNginxController
ID: MyNginxController
Image(s): dockerfile/nginx
Selector: replicationController=MyNginxController
Labels:
Replicas: 2 current / 2 desired
Pods Status: 2 running / 0 waiting / 0 terminated
```

### Other notes

* I am currently using [spf13/cobra](https://github.com/spf13/cobra) but am also considering [codegangsta/cli](https://github.com/codegangsta/cli). The latter may allow us to write out the command definitions in a cleaner way and support bash autocompletion, but the former allows persistent flags. Open to using either one.
* Some of these commands (espeically `get` commands that show a lot of info) may result in lots of queries to the server. There are several ways to handle this: (1) don't consider it an issue, (2) offer a "succinct mode" that tries to do as little as possible and (3) over time backport functionality that is particularly useful directly into apiserver as new API endpoints. Especially with (3), you could consider kubecfg a proving ground for new convenience functionality to see whether it's worth implementing in apiserver directly.

### File layout

* cmd/kubecfg2/kubecfg2.go - All cobra and CLI-related code remains in this file/package.
* pkg/kubecfg2/.go - All logic per subcommand lives in one file per subcommand.
* pkg/kubecfg2/kubecfg2.go - Common functions used by cmd/kubecfg2 and pkg/kubecfg2 packages.