Repository: kubernetes
Issue: Proposal: Long term evolution of runtime.Scheme / conversion.Scheme
Labels: area/api,area/apiserver,sig/api-machinery,kind/feature,priority/important-longterm,lifecycle/frozen

Continued from https://github.com/GoogleCloudPlatform/kubernetes/issues/2306

A runtime.Scheme combines a few concepts:
- A registry of APIVersion -> Kind string -> Go object
- A library of conversion routines which includes APIVersion -> Go object as well as Go object -> Go object
- An encoding mechanism based around JSON

In order to better support multiple API patterns grouped together (Kubernetes user API, Kubelet API, OpenShift API, _future extension API_) these assumptions will start to break down.  
#### Known problems:

A 3rd party API may have a "v1".  That API may define an object "List", that they want to convert to a Kubernetes "v1" "List".  In our current setup, it would be impossible for those two API objects to be compiled into the same runtime.Scheme (because they both want to reserve "v1/List" to different objects).  It would also be impossible to convert from the third party API "v1" "List" to a Kubernetes "v1" "List" because they exist in different conversion schemes.

A 3rd party API may want to reuse the Kubernetes "Status" object in their own API schema for their version "v1beta1".  It would be impossible for them to use the "v1" Kubernetes status object without having a separate runtime.Scheme, but their client library may want to convert both Kubernetes v1 objects to their internal type.

Finally, we may want to introduce new serialization types for objects - Gob, Protobuf, Msgpack, JSON+snappy, for various use cases (more efficient storage).  The coupling of JSON to runtime.Scheme complicates those conversions or makes them less efficient.
#### Types of problems we want to solve:
1. It should be possible to take arbitrary serialized data and convert it to a versioned Go struct - call this "marshalling/unmarshalling".  The interface for this is a `Codec`.  There may be many codecs.
   1. Where possible, we want to reuse the underlying infrastructure for marshaling and unmarshalling that exists in go - "encoding/json" / "encoding/gob" / "protobufs" efficiently.  
   2. It's likely that there exists one canonical "marshaller" for most objects, but there may be alternate mechanisms.  For example, JSON is canonical for Kube, but we may occasionally want to marshal an annotated YAML object that has description comments for each field interleaved.
   3. There are places where we want to convert `map[string]interface{}` (generic JSON object representation) or a `map[string][]string` (url.Values) into a versioned Go struct, which is dependent on a type of marshaling (i.e. following JSON rules, or Query parameter rules).
2. It should be possible to convert a versioned Go struct into a different versioned Go struct (typically by going to an intermediate format) on the server.  This is "object versioning".
   1. "Object versioning" requires the registration of an object Kind into an APIVersion for a specific API group.  This was the original intent of runtime.Scheme.
3. It should be possible to convert arbitrary Go structs to different Go structs.  This is "conversion".
   1. Object versioning is a specific subset of conversion
   2. We should try to make conversion less dependent on scheme?
4. ??
#### Consumers:
1. The APIServer needs to take incoming objects with a content-type (marshaling format), determine the Kind (whether it is accepted by the endpoint), verify the provided APIVersion is allowed (or default it), and then unmarshal it to a versioned Go struct.  We then want to use "object versioning" to return an internal representation.  It also needs to take internal representations, convert them to an external object version, and then marshal that object version to a given content-type.
2. The Go client needs to read responses from the server (unmarshal), determine the Kind of the response, verify the APIVersion is recognized, and then convert it to an internal representation (object versioning) that the client can use to present information to a user.  
3. The Go command line tool needs to take a representation returned by the server in one version, convert it to another version, and process that other version (talk to API v2, convert to API v1, output to template on CLI).
4. The Go command line tool needs to read objects on disk in known marshaller formats, be able to transform those objects in specific ways (set namespace for v1beta1 and v1beta3) or perform Swagger specific validation.  The Go command line tool must support taking objects that it was not compiled with and be able to transmit them to a compatible API server that is not Kubernetes once we want to support true extensions.
5. ??

Still a WIP, trying to gather thoughts.