Proposal for new kubecfg design (kubectl)

***UPDATE: This proposal was reworked many times throughout this PR. I am keeping this parent message the same for historical purposes, but you can find the closest description of the final design in [this comment](https://github.com/GoogleCloudPlatform/kubernetes/pull/1325#issuecomment-57416174) (with the exception that `inspect` became `describe`).***

### 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

*Only a subset of these have been implemented in the attached commit.*

* `kubecfg2` - Parent command.
  * `pods`
    * `list [<id>]` - 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 <id>` - 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 <id>` - Delete a pod.
    * `create [-f <filename>]` - In the future we can accept directories or even data from stdin.
  * `rc` - For replication controllers. Happy to use a different abbreviation but replicationControllers seemed too long.
    * `list [<id>]`
    * `get <id>` - 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 terminated, 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 &lt;X more ...&gt;, making debugging even easier.
    * `create [-f <filename>]`
    * `update [-f <filename>]`
    * `delete <id>` - I have removed the delete/stop/rm replication controller confusion in favor of just `delete` and `resize`, where delete takes an optional --force flag if replicas > 0.
    * `resize <id> <replicas>`
    * *Removed* `rollingupdate <controller> <image> <time>` - I've included this here for parity but I would like to propose taking it out. 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 that can look at more components in the infrastructure than just kubernetes.
  * `minions`
    * `list [<id>]`
    * `get <id>`
  * `services`
    * `list [<id>]`
    * `get <id>`
    * `create [-f <filename>]`
    * `update [-f <filename>]`
    * `delete <id>`
    * *Postponed* `resolve <id>` - 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.
  * *Postponed* `submit [<filename>...]` - 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.
  * *Postponed* `diff [<filename>...]` - A dry-run version of `submit`.
  * `run [-p <port spec>] <image> <replicas> <controller>` - Same as today.

### Examples

Here is what the current commit produces:

*These examples are out of date - see [this comment](https://github.com/GoogleCloudPlatform/kubernetes/pull/1325#issuecomment-56786115) for the latest.*

```
$ 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 [<id>] [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:         <none>
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 (especially `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/&lt;subcommand&gt;.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.

### Open Questions
* Can we leave rollingupdate out of this version for the merge? If it's needed for demo purposes, can it be reimplemented somewhere outside of this tool?
* @erictune pointed out that `get` is not the best name for above. `info` and `details` are other options but ideas here are welcome.

For name vs id, I don't like having to always prefix with "name:" or "id:"... it feels clumsy for such a common operation. Can we use the @id syntax that @smarterclayton recommended? So:

```
[get | delete | describe] <kind> [@][<id-or-name>]
```

```
get pods
get pod nifty
get pod @1234-56-7890-234234-456456
get service @2345-56-7890-234234-456456

get nifty // automatically errors because can't use name without kind
get @1234-56-7890-234234-456456 // maybe we can support it in the future
```

We can use kubectl as a testing ground for the syntax and if it works elegantly, we can broaden it to be a more general way to reference ID's. (In the future the `<type>:<value>` style should be supported as well, we can even support name:, id:, label:, stuff like that. But we should ideally avoid creating that syntax quite yet.)

On the topic of -f conflicting, I actually think it makes more sense for "modify" commands like create, update, and delete, and "read" commands like get and describe to act similar to their respective groups. And I think it makes sense to be able to provide the json file that you just used to create a (named) pod to delete it as well. I'd rather make delete look more like its group than mix it with get and describe.

The only reason for the additional -i flag, which is the only thing that makes delete look different, is the idea that I wanted to make it convenient to issue a delete since that's the only "modify" command where it's possible you rm'd the json file you were using to make creates and updates before you sent the command to kubecfg. With the above change we could keep the -i flag format or we could autodetect whether your first argument is JSON or not - if not we fall back to get/describe semantics:

```
delete -i pod,1234-56-7890-234234-456456
delete -i pod,nifty
delete {"kind": "Pod", "name:" "nifty", ...}

OR

delete pod,1234-56-7890-234234-456456
delete pod,nifty
delete {"kind": "Pod", "name:" "nifty", ...}
```

I'm open to a better way of specifying this, but I think abandoning the functionality to use a json file doesn't make sense.