Code change:
container.Add(ws) } <ins> // stripVersionEncoder strips APIVersion field from the encoding output. It's // used to keep the responses at the discovery endpoints backward compatible // with release-1.1, when the responses have empty APIVersion. type stripVersionEncoder struct { encoder    runtime.Encoder serializer runtime.Serializer } func (c stripVersionEncoder) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unversioned.GroupVersion) error { buf := bytes.NewBuffer([]byte{}) err := c.encoder.EncodeToStream(obj, buf, overrides...) if err != nil { return err } roundTrippedObj, gvk, err := c.serializer.Decode(buf.Bytes(), nil, nil) if err != nil { return err } gvk.Group = "" gvk.Version = "" roundTrippedObj.GetObjectKind().SetGroupVersionKind(gvk) return c.serializer.EncodeToStream(roundTrippedObj, w) } // StripVersionNegotiatedSerializer will return stripVersionEncoder when // EncoderForVersion is called. See comments for stripVersionEncoder. type StripVersionNegotiatedSerializer struct { runtime.NegotiatedSerializer } func (n StripVersionNegotiatedSerializer) EncoderForVersion(serializer runtime.Serializer, gv unversioned.GroupVersion) runtime.Encoder { encoder := n.NegotiatedSerializer.EncoderForVersion(serializer, gv) return stripVersionEncoder{encoder, serializer} } func keepUnversioned(group string) bool { return group == "" || group == "extensions" } </ins> // Adds a service to return the supported api versions at /apis. func AddApisWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, f func(req *restful.Request) []unversioned.APIGroup) { <del> rootAPIHandler := RootAPIHandler(s, f) </del> <ins> // Because in release 1.1, /apis returns response with empty APIVersion, we // use StripVersionNegotiatedSerializer to keep the response backwards // compatible. ss := StripVersionNegotiatedSerializer{s} rootAPIHandler := RootAPIHandler(ss, f) </ins> ws := new(restful.WebService) ws.Path(apiPrefix) ws.Doc("get available API versions")

Related discussion:
text: 1-master-step1- api-versions] [] error: Couldn't get available api versions from server: no kind "APIVersions" is registered for version "v1" [] 0xc208382fa0 exit status 1 true [0xc208627148 0xc208627168 0xc208627188] [0xc208627148 0xc208627168 0xc208627188] [0xc208627160 0xc208627180] [0x6d81a0 0x6d81a0] 0xc2082fb2c0}: Command stdout: stderr: error: Couldn't get available api versions from server: no kind "APIVersions" is registered for version "v1" not to have occurred* See and Investigating. cc
Okiedokie. Looks like the v1.1 client is getting a response from the v1.2 master, but the v1.1 client doesn't know how to handle the v1 APIVersions object, because in v1.1, that object was never expected to have an . From a 1.1 server, we get which doesn't include a . We should expect to have plenty of pre-v1.1.7 clients floating around, and releasing a fixed v1.1.8 probably isn't going to solve this; if we want to be backward compatible, we need to not return an string with unversioned kinds like . Looking into more details about how we got here... cc cc
I have a maybe feeling that this is caused by ? In particular, we went from: to
Probably it's caused by this:
Let me double check the code. cc
What about that line? I've never dealt with the version negotiation; should the server and client be negotiating in a way that the server can return an object without ?
More precisely it's this line: This line sets the version to "v1". In , during encoding, we set unversioned object's APIVersion field to "v1".
I think in the long run, because we expect to move many unversioned types to group "common", so they should be versioned, so making APIVersion=v1 is the right move. Back to the backwards compatibility issue, how's the situation at other url, like http://127.0.0.1:8080/apis/extensions?