mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Strip version when encoding discovery API objects at endpoints that exist since release 1.1
This commit is contained in:
parent
4d59d700c2
commit
39838745e5
@ -221,7 +221,11 @@ func serviceErrorHandler(s runtime.NegotiatedSerializer, requestResolver *Reques
|
||||
func AddApiWebService(s runtime.NegotiatedSerializer, container *restful.Container, apiPrefix string, getAPIVersionsFunc func(req *restful.Request) *unversioned.APIVersions) {
|
||||
// TODO: InstallREST should register each version automatically
|
||||
|
||||
versionHandler := APIVersionHandler(s, getAPIVersionsFunc)
|
||||
// Because in release 1.1, /api returns response with empty APIVersion, we
|
||||
// use StripVersionNegotiatedSerializer to keep the response backwards
|
||||
// compatible.
|
||||
ss := StripVersionNegotiatedSerializer{s}
|
||||
versionHandler := APIVersionHandler(ss, getAPIVersionsFunc)
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(apiPrefix)
|
||||
ws.Doc("get available API versions")
|
||||
@ -233,9 +237,52 @@ func AddApiWebService(s runtime.NegotiatedSerializer, container *restful.Contain
|
||||
container.Add(ws)
|
||||
}
|
||||
|
||||
// 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"
|
||||
}
|
||||
|
||||
// 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) {
|
||||
rootAPIHandler := RootAPIHandler(s, f)
|
||||
// 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)
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(apiPrefix)
|
||||
ws.Doc("get available API versions")
|
||||
@ -250,7 +297,14 @@ func AddApisWebService(s runtime.NegotiatedSerializer, container *restful.Contai
|
||||
// Adds a service to return the supported versions, preferred version, and name
|
||||
// of a group. E.g., a such web service will be registered at /apis/extensions.
|
||||
func AddGroupWebService(s runtime.NegotiatedSerializer, container *restful.Container, path string, group unversioned.APIGroup) {
|
||||
groupHandler := GroupHandler(s, group)
|
||||
ss := s
|
||||
if keepUnversioned(group.Name) {
|
||||
// Because in release 1.1, /apis/extensions returns response with empty
|
||||
// APIVersion, we use StripVersionNegotiatedSerializer to keep the
|
||||
// response backwards compatible.
|
||||
ss = StripVersionNegotiatedSerializer{s}
|
||||
}
|
||||
groupHandler := GroupHandler(ss, group)
|
||||
ws := new(restful.WebService)
|
||||
ws.Path(path)
|
||||
ws.Doc("get information of a group")
|
||||
@ -265,7 +319,14 @@ func AddGroupWebService(s runtime.NegotiatedSerializer, container *restful.Conta
|
||||
// Adds a service to return the supported resources, E.g., a such web service
|
||||
// will be registered at /apis/extensions/v1.
|
||||
func AddSupportedResourcesWebService(s runtime.NegotiatedSerializer, ws *restful.WebService, groupVersion unversioned.GroupVersion, apiResources []unversioned.APIResource) {
|
||||
resourceHandler := SupportedResourcesHandler(s, groupVersion, apiResources)
|
||||
ss := s
|
||||
if keepUnversioned(groupVersion.Group) {
|
||||
// Because in release 1.1, /apis/extensions/v1beta1 returns response
|
||||
// with empty APIVersion, we use StripVersionNegotiatedSerializer to
|
||||
// keep the response backwards compatible.
|
||||
ss = StripVersionNegotiatedSerializer{s}
|
||||
}
|
||||
resourceHandler := SupportedResourcesHandler(ss, groupVersion, apiResources)
|
||||
ws.Route(ws.GET("/").To(resourceHandler).
|
||||
Doc("get available resources").
|
||||
Operation("getAPIResources").
|
||||
|
@ -260,6 +260,82 @@ func TestGetNodeAddresses(t *testing.T) {
|
||||
assert.Equal([]string{"127.0.0.2", "127.0.0.2"}, addrs)
|
||||
}
|
||||
|
||||
// Because we need to be backwards compatible with release 1.1, at endpoints
|
||||
// that exist in release 1.1, the responses should have empty APIVersion.
|
||||
func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
|
||||
master, etcdserver, _, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
server := httptest.NewServer(master.HandlerContainer.ServeMux)
|
||||
|
||||
// /api exists in release-1.1
|
||||
resp, err := http.Get(server.URL + "/api")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
apiVersions := unversioned.APIVersions{}
|
||||
assert.NoError(decodeResponse(resp, &apiVersions))
|
||||
assert.Equal(apiVersions.APIVersion, "")
|
||||
|
||||
// /api/v1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/api/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList := unversioned.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
groupList := unversioned.APIGroupList{}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
assert.Equal(groupList.APIVersion, "")
|
||||
|
||||
// /apis/extensions exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group := unversioned.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "")
|
||||
|
||||
// /apis/extensions/v1beta1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions/v1beta1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = unversioned.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis/autoscaling doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group = unversioned.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "v1")
|
||||
|
||||
// apis/autoscaling/v1 doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = unversioned.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "v1")
|
||||
|
||||
}
|
||||
|
||||
func TestDiscoveryAtAPIS(t *testing.T) {
|
||||
master, etcdserver, config, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
Loading…
Reference in New Issue
Block a user